diff options
37 files changed, 109 insertions, 4386 deletions
diff --git a/emulators/qemu/Makefile b/emulators/qemu/Makefile index 6b242682f0e..edbb620a825 100644 --- a/emulators/qemu/Makefile +++ b/emulators/qemu/Makefile @@ -1,7 +1,7 @@ -# $NetBSD: Makefile,v 1.282 2021/06/22 04:09:06 thorpej Exp $ +# $NetBSD: Makefile,v 1.283 2021/08/27 03:32:37 ryoon Exp $ -DISTNAME= qemu-6.0.0 -PKGREVISION= 2 +DISTNAME= qemu-6.1.0 +PKGNAME= ${DISTNAME:S/-rc/rc/} CATEGORIES= emulators MASTER_SITES= https://download.qemu.org/ EXTRACT_SUFX= .tar.xz @@ -20,6 +20,7 @@ UNLIMIT_RESOURCES= datasize HAS_CONFIGURE= yes PYTHON_VERSIONED_DEPENDENCIES= sphinx:tool +BUILD_DEPENDS+= ${PYPKGPREFIX}-sphinx-rtd-theme>=0.4.3:../../textproc/py-sphinx-rtd-theme SUBST_CLASSES+= sphinx-build SUBST_STAGE.sphinx-build= pre-configure @@ -27,7 +28,7 @@ SUBST_MESSAGE.sphinx-build= Fix hardcoded sphinx-build SUBST_FILES.sphinx-build+= configure SUBST_FILES.sphinx-build+= docs/meson.build SUBST_FILES.sphinx-build+= roms/skiboot/doc/Makefile -SUBST_FILES.sphinx-build+= roms/u-boot/Documentation/Makefile +SUBST_FILES.sphinx-build+= roms/u-boot/doc/Makefile SUBST_SED.sphinx-build+= -e 's/sphinx-build/sphinx-build-${PYVERSSUFFIX}/g' .include "options.mk" @@ -74,7 +75,6 @@ NOT_PAX_MPROTECT_SAFE+= bin/qemu-system-mips NOT_PAX_MPROTECT_SAFE+= bin/qemu-system-mips64 NOT_PAX_MPROTECT_SAFE+= bin/qemu-system-mips64el NOT_PAX_MPROTECT_SAFE+= bin/qemu-system-mipsel -NOT_PAX_MPROTECT_SAFE+= bin/qemu-system-moxie NOT_PAX_MPROTECT_SAFE+= bin/qemu-system-nios2 NOT_PAX_MPROTECT_SAFE+= bin/qemu-system-or1k NOT_PAX_MPROTECT_SAFE+= bin/qemu-system-ppc diff --git a/emulators/qemu/PLIST b/emulators/qemu/PLIST index 776e9f6b7fb..6c828a637e9 100644 --- a/emulators/qemu/PLIST +++ b/emulators/qemu/PLIST @@ -1,4 +1,4 @@ -@comment $NetBSD: PLIST,v 1.76 2021/05/26 00:59:44 mcf Exp $ +@comment $NetBSD: PLIST,v 1.77 2021/08/27 03:32:37 ryoon Exp $ bin/elf2dmp ${PLIST.aarch64}bin/qemu-aarch64 ${PLIST.aarch64_be}bin/qemu-aarch64_be @@ -35,9 +35,7 @@ ${PLIST.riscv64}bin/qemu-riscv64 ${PLIST.s390x}bin/qemu-s390x ${PLIST.sh4}bin/qemu-sh4 ${PLIST.sh4eb}bin/qemu-sh4eb -${PLIST.sparc}bin/qemu-sparc ${PLIST.sparc32plus}bin/qemu-sparc32plus -${PLIST.sparc64}bin/qemu-sparc64 bin/qemu-storage-daemon bin/qemu-system-aarch64 bin/qemu-system-alpha @@ -53,7 +51,6 @@ bin/qemu-system-mips bin/qemu-system-mips64 bin/qemu-system-mips64el bin/qemu-system-mipsel -bin/qemu-system-moxie bin/qemu-system-nios2 bin/qemu-system-or1k bin/qemu-system-ppc @@ -73,12 +70,12 @@ bin/qemu-system-xtensaeb ${PLIST.x86_64}bin/qemu-x86_64 ${PLIST.xtensa}bin/qemu-xtensa ${PLIST.xtensaeb}bin/qemu-xtensaeb +include/qemu-plugin.h ${PLIST.bridge-helper}libexec/qemu-bridge-helper ${PLIST.virtfs-proxy-helper}libexec/virtfs-proxy-helper man/man1/qemu-img.1 man/man1/qemu-storage-daemon.1 man/man1/qemu.1 -${PLIST.virtfs-proxy-helper}man/man1/virtfs-proxy-helper.1 man/man7/qemu-block-drivers.7 man/man7/qemu-cpu-models.7 man/man7/qemu-ga-ref.7 @@ -87,26 +84,36 @@ man/man7/qemu-storage-daemon-qmp-ref.7 man/man8/qemu-ga.8 man/man8/qemu-nbd.8 man/man8/qemu-pr-helper.8 +${PLIST.virtfs-proxy-helper}man/man1/virtfs-proxy-helper.1 share/applications/qemu.desktop share/doc/qemu/.buildinfo share/doc/qemu/Makefile.multinode-NetBSD +share/doc/qemu/about/build-platforms.html +share/doc/qemu/about/deprecated.html +share/doc/qemu/about/index.html +share/doc/qemu/about/license.html +share/doc/qemu/about/removed-features.html share/doc/qemu/devel/atomics.html share/doc/qemu/devel/bitops.html share/doc/qemu/devel/block-coroutine-wrapper.html share/doc/qemu/devel/build-system.html +share/doc/qemu/devel/ci.html share/doc/qemu/devel/clocks.html share/doc/qemu/devel/code-of-conduct.html share/doc/qemu/devel/conflict-resolution.html share/doc/qemu/devel/control-flow-integrity.html share/doc/qemu/devel/decodetree.html +share/doc/qemu/devel/ebpf_rss.html share/doc/qemu/devel/fuzzing.html share/doc/qemu/devel/index.html share/doc/qemu/devel/kconfig.html share/doc/qemu/devel/loads-stores.html share/doc/qemu/devel/memory.html share/doc/qemu/devel/migration.html +share/doc/qemu/devel/modules.html share/doc/qemu/devel/multi-process.html share/doc/qemu/devel/multi-thread-tcg.html +share/doc/qemu/devel/qapi-code-gen.html share/doc/qemu/devel/qgraph.html share/doc/qemu/devel/qom.html share/doc/qemu/devel/qtest.html @@ -120,8 +127,12 @@ share/doc/qemu/devel/tcg-plugins.html share/doc/qemu/devel/tcg.html share/doc/qemu/devel/testing.html share/doc/qemu/devel/tracing.html +share/doc/qemu/devel/ui.html +share/doc/qemu/devel/vfio-migration.html +share/doc/qemu/devel/writing-qmp-commands.html share/doc/qemu/genindex.html share/doc/qemu/index.html +share/doc/qemu/interop/barrier.html share/doc/qemu/interop/bitmaps.html share/doc/qemu/interop/dbus-vmstate.html share/doc/qemu/interop/dbus.html @@ -148,12 +159,20 @@ share/doc/qemu/specs/tpm.html share/doc/qemu/system/arm/aspeed.html share/doc/qemu/system/arm/collie.html share/doc/qemu/system/arm/cpu-features.html +share/doc/qemu/system/arm/cubieboard.html share/doc/qemu/system/arm/digic.html +share/doc/qemu/system/arm/emcraft-sf2.html +share/doc/qemu/system/arm/emulation.html share/doc/qemu/system/arm/gumstix.html +share/doc/qemu/system/arm/highbank.html +share/doc/qemu/system/arm/imx25-pdk.html share/doc/qemu/system/arm/integratorcp.html +share/doc/qemu/system/arm/kzm.html +share/doc/qemu/system/arm/mainstone.html share/doc/qemu/system/arm/mps2.html share/doc/qemu/system/arm/musca.html share/doc/qemu/system/arm/musicpal.html +share/doc/qemu/system/arm/nrf.html share/doc/qemu/system/arm/nseries.html share/doc/qemu/system/arm/nuvoton.html share/doc/qemu/system/arm/orangepi.html @@ -163,15 +182,24 @@ share/doc/qemu/system/arm/realview.html share/doc/qemu/system/arm/sabrelite.html share/doc/qemu/system/arm/sbsa.html share/doc/qemu/system/arm/stellaris.html +share/doc/qemu/system/arm/stm32.html share/doc/qemu/system/arm/sx1.html share/doc/qemu/system/arm/versatile.html share/doc/qemu/system/arm/vexpress.html share/doc/qemu/system/arm/virt.html share/doc/qemu/system/arm/xlnx-versal-virt.html share/doc/qemu/system/arm/xscale.html -share/doc/qemu/system/build-platforms.html +share/doc/qemu/system/authz.html +share/doc/qemu/system/barrier.html +share/doc/qemu/system/bootindex.html share/doc/qemu/system/cpu-hotplug.html -share/doc/qemu/system/deprecated.html +share/doc/qemu/system/device-emulation.html +share/doc/qemu/system/devices/ivshmem.html +share/doc/qemu/system/devices/net.html +share/doc/qemu/system/devices/nvme.html +share/doc/qemu/system/devices/usb.html +share/doc/qemu/system/devices/vhost-user.html +share/doc/qemu/system/devices/virtio-pmem.html share/doc/qemu/system/gdb.html share/doc/qemu/system/generic-loader.html share/doc/qemu/system/guest-loader.html @@ -180,19 +208,16 @@ share/doc/qemu/system/i386/pc.html share/doc/qemu/system/images.html share/doc/qemu/system/index.html share/doc/qemu/system/invocation.html -share/doc/qemu/system/ivshmem.html share/doc/qemu/system/keys.html -share/doc/qemu/system/license.html share/doc/qemu/system/linuxboot.html share/doc/qemu/system/managed-startup.html share/doc/qemu/system/monitor.html share/doc/qemu/system/multi-process.html share/doc/qemu/system/mux-chardev.html -share/doc/qemu/system/net.html -share/doc/qemu/system/nvme.html share/doc/qemu/system/ppc/embedded.html share/doc/qemu/system/ppc/powermac.html share/doc/qemu/system/ppc/powernv.html +share/doc/qemu/system/ppc/ppce500.html share/doc/qemu/system/ppc/prep.html share/doc/qemu/system/ppc/pseries.html share/doc/qemu/system/pr-manager.html @@ -200,15 +225,17 @@ share/doc/qemu/system/qemu-block-drivers.html share/doc/qemu/system/qemu-cpu-models.html share/doc/qemu/system/qemu-manpage.html share/doc/qemu/system/quickstart.html -share/doc/qemu/system/removed-features.html share/doc/qemu/system/riscv/microchip-icicle-kit.html +share/doc/qemu/system/riscv/shakti-c.html share/doc/qemu/system/riscv/sifive_u.html +share/doc/qemu/system/riscv/virt.html share/doc/qemu/system/s390x/3270.html share/doc/qemu/system/s390x/bootdevices.html share/doc/qemu/system/s390x/css.html share/doc/qemu/system/s390x/protvirt.html share/doc/qemu/system/s390x/vfio-ap.html share/doc/qemu/system/s390x/vfio-ccw.html +share/doc/qemu/system/secrets.html share/doc/qemu/system/security.html share/doc/qemu/system/target-arm.html share/doc/qemu/system/target-avr.html @@ -224,9 +251,7 @@ share/doc/qemu/system/target-sparc64.html share/doc/qemu/system/target-xtensa.html share/doc/qemu/system/targets.html share/doc/qemu/system/tls.html -share/doc/qemu/system/usb.html share/doc/qemu/system/virtio-net-failover.html -share/doc/qemu/system/virtio-pmem.html share/doc/qemu/system/vnc-security.html share/doc/qemu/tools/index.html share/doc/qemu/tools/qemu-img.html @@ -363,4 +388,3 @@ share/qemu/vgabios-stdvga.bin share/qemu/vgabios-virtio.bin share/qemu/vgabios-vmware.bin share/qemu/vgabios.bin -@pkgdir var/run diff --git a/emulators/qemu/distinfo b/emulators/qemu/distinfo index 2414809504c..5bc7a49b8d3 100644 --- a/emulators/qemu/distinfo +++ b/emulators/qemu/distinfo @@ -1,57 +1,27 @@ -$NetBSD: distinfo,v 1.182 2021/07/09 21:08:33 schmonz Exp $ +$NetBSD: distinfo,v 1.183 2021/08/27 03:32:37 ryoon Exp $ SHA1 (palcode-clipper-qemu-5.2.0nb8) = ddbf1dffb7c2b2157e0bbe9fb7db7e57105130b1 RMD160 (palcode-clipper-qemu-5.2.0nb8) = 3f9fe19a40f7ca72ecfe047d1449e55b63cba3ee SHA512 (palcode-clipper-qemu-5.2.0nb8) = 33695d6001d86a19793a92d5e31775607c4dfc9ab9eea019ea6c4d543a2e11e8c07f83cca4934811a13ef829b528737ea37d9d2aaf66cba6f2746d44d2aa0b43 Size (palcode-clipper-qemu-5.2.0nb8) = 159808 bytes -SHA1 (qemu-6.0.0.tar.xz) = 131854b10d8c1614ae137c647aa31b756782ba2e -RMD160 (qemu-6.0.0.tar.xz) = 0785bb4c32f1e9d23dcdfad562f18d232677a0c6 -SHA512 (qemu-6.0.0.tar.xz) = ee3ff00aebec4d8891d2ff6dabe4e667e510b2a4fe3f6190aa34673a91ea32dcd2db2e9bf94c2f1bf05aa79788f17cfbbedc6027c0988ea08a92587b79ee05e4 -Size (qemu-6.0.0.tar.xz) = 107333232 bytes -SHA1 (patch-accel_Kconfig) = d343285a8b548d2d6387b92576aed801265d2b24 +SHA1 (qemu-6.1.0.tar.xz) = aae5ef7761b5f2fc45f0076219f1249da86f94b5 +RMD160 (qemu-6.1.0.tar.xz) = 00f21e102c9ca70c154b770d0094fd48568bbdd5 +SHA512 (qemu-6.1.0.tar.xz) = 3378ae21c75b77ee6a759827f1fcf7b2a50a0fef07e3b0e89117108022a8d8655fa977e4d65596f4f24f7c735c6594d44b0c6f69732ea4465e88a7406b1d5d3c +Size (qemu-6.1.0.tar.xz) = 111258808 bytes SHA1 (patch-backends_tpm_tpm__ioctl.h) = fbd6c877ad605f7120290efbb0ac653c69f351de -SHA1 (patch-configure) = d94427a90bbb8e4d1347503e5583b4966b039e37 SHA1 (patch-hw-mips-Kconfig) = c7199ad26ac45116ab4d38252db4234ae93bdf9a -SHA1 (patch-hw-mips-mipssim.c) = f701897f2c2bee4a8c3fa5222903789f991a663a -SHA1 (patch-hw_alpha_alpha_sys.h) = 5908698208937ff9eb0bf1c504e1144af3d1bcc4 -SHA1 (patch-hw_alpha_dp264.c) = 856304784f098863728ecac3d0a9287aa22190d7 -SHA1 (patch-hw_alpha_typhoon.c) = 1bed5cd6f355c4163585c5331356ebf38c5c3a16 +SHA1 (patch-hw-mips-mipssim.c) = 1f682b74b34398b3ff15f9e7f24a85f4b8bb4853 SHA1 (patch-hw_core_uboot__image.h) = 17eef02349343c5fcfb7a4069cb6f8fd11efcb59 SHA1 (patch-hw_display_omap__dss.c) = 6b13242f28e32346bc70548c216c578d98fd3420 SHA1 (patch-hw_i386_acpi-build.c) = 7d23d09f71917cedca4226fd22baa45bcb0f7d33 -SHA1 (patch-hw_mips_meson.build) = ff4bec33d9d2f86a425e02928aa3b6963c22da68 +SHA1 (patch-hw_mips_meson.build) = d9a07a81fe6d3c9e2bd45f41fe876cd927a40ced SHA1 (patch-hw_net_etraxfs__eth.c) = e5dd1661d60dbcd27b332403e0843500ba9544bc SHA1 (patch-hw_net_xilinx__axienet.c) = ebcd2676d64ce6f31e4a8c976d4fdf530ad5e8b7 SHA1 (patch-hw_rtc_mc146818rtc.c) = cc7a3b28010966b65b7a16db756226ac2669f310 SHA1 (patch-hw_scsi_scsi-disk.c) = fdbf2f962a6dcb1a115a7f8a5b8790ff9295fb33 SHA1 (patch-hw_usb_dev-mtp.c) = 94ddf53a41cc75810cfece1b8aef1831fab4ce43 -SHA1 (patch-include_sysemu_hw__accel.h) = a3cd022368a074e30dd3958932a006fa0fe011a6 -SHA1 (patch-include_sysemu_kvm.h) = 9847abe3be70bd708a521310f5d5515e45a1a5a0 -SHA1 (patch-include_sysemu_nvmm.h) = 7e49abdc7dc6a03f293780c63ac6c242d3914d15 -SHA1 (patch-meson.build) = ec26f7df6789ac6880ac2ac1f8b0f22ec9bb31f5 -SHA1 (patch-meson__options.txt) = 050adf1d5c07dc211fdafde7a21e2afe52db9169 +SHA1 (patch-include_sysemu_nvmm.h) = 2cf9ea36c77570136b0678fe3b1c126ca7fa04cd +SHA1 (patch-meson.build) = 086400b3eebd0d5ce91af7779fa4f2a56d953542 SHA1 (patch-net_tap-solaris.c) = cc953c9a624dd55ace4e130d0b31bbfb956c17d5 -SHA1 (patch-nvmm-accel-ops.c) = 23ef13420a61d8bfa78f36ed7eae2e1523464617 -SHA1 (patch-nvmm-accel-ops.h) = 101b4f3f2a5775db4c93ffcf10b150e8545a3655 -SHA1 (patch-nvmm-all.c) = 93d33e285b616a20ad2af550bef31e88c55f6a22 -SHA1 (patch-qemu-options.hx) = 2e68ce28c9a678a666c3f23a0c1369d3568aa1eb -SHA1 (patch-roms_qemu-palcode_hwrpb.h) = ae7b4c0680367af6f740d62a54dc86352128d76f -SHA1 (patch-roms_qemu-palcode_init.c) = 7a0ebcd86f4106318791e7d90273fb55a424f1b8 -SHA1 (patch-roms_qemu-palcode_memcpy.c) = 7761774ae9092d0f494deaf302d663ba479a09cf -SHA1 (patch-roms_qemu-palcode_memset.c) = 55fa4e52e03a351eb98475e7c4755e5edc409e6c -SHA1 (patch-roms_qemu-palcode_pal.S) = fd13cf4ff7a4ba48a9cbb773d520eacf06615301 -SHA1 (patch-roms_qemu-palcode_pci.c) = 1d5b240fd6c940cbbe8518e4db529adba23d6fec -SHA1 (patch-roms_qemu-palcode_pci.h) = 081c9d6d9955be24fd19455ae653339cdb133f02 -SHA1 (patch-roms_qemu-palcode_printf.c) = 7fb158f85bd1be9a939850d9d86175013f7a142b -SHA1 (patch-roms_qemu-palcode_protos.h) = 60cf9db5544cb842207a893a78fa6bbe45af4c71 -SHA1 (patch-roms_qemu-palcode_sys-clipper.h) = 8983d7072b1c1e66bf0a18d2e49e503745692a46 -SHA1 (patch-roms_qemu-palcode_vgaio.c) = c8d7adc053cd6655f005527d16647611040c09d2 SHA1 (patch-roms_u-boot-sam460ex_Makefile) = 3a1bbf19b1422c10ebdd819eb0b711fafc78e2f2 -SHA1 (patch-roms_u-boot_tools_imx8m__image.sh) = e4c452062f40569e33aa93eec4a65bd3af2e74fc -SHA1 (patch-target_alpha_translate.c) = c4dc5053122a5a76ba2e7f0b27076f2b42247953 -SHA1 (patch-target_i386_meson.build) = 0b6430825e1f5715f6deea556043b7e5063cf10a -SHA1 (patch-target_i386_nvmm_meson.build) = c773fbed28a87f53263ab5299a63ca77423d164f -SHA1 (patch-target_i386_nvmm_nvmm-accel-ops.c) = fdc29ccd0fcd47b72e7802655fe92b08f7d22bb9 -SHA1 (patch-target_i386_nvmm_nvmm-accel-ops.h) = 74d6442e1ac1cdf187996f3dd82bb3efddc002ec -SHA1 (patch-target_i386_nvmm_nvmm-all.c) = 6370f1f6336546b24d9c3493cd0b27ca6843f35d SHA1 (patch-target_sparc_translate.c) = 7ec2add2fd808facb48b9a66ccc345599251bf76 diff --git a/emulators/qemu/patches/patch-accel_Kconfig b/emulators/qemu/patches/patch-accel_Kconfig deleted file mode 100644 index a3fe36abcff..00000000000 --- a/emulators/qemu/patches/patch-accel_Kconfig +++ /dev/null @@ -1,14 +0,0 @@ -$NetBSD: patch-accel_Kconfig,v 1.1 2021/05/24 14:22:08 ryoon Exp $ - ---- accel/Kconfig.orig 2021-04-29 17:18:58.000000000 +0000 -+++ accel/Kconfig -@@ -1,6 +1,9 @@ - config WHPX - bool - -+config NVMM -+ bool -+ - config HAX - bool - diff --git a/emulators/qemu/patches/patch-configure b/emulators/qemu/patches/patch-configure deleted file mode 100644 index ac9dcc7ce11..00000000000 --- a/emulators/qemu/patches/patch-configure +++ /dev/null @@ -1,40 +0,0 @@ -$NetBSD: patch-configure,v 1.32 2021/05/24 14:22:08 ryoon Exp $ - ---- configure.orig 2021-04-29 17:18:59.000000000 +0000 -+++ configure -@@ -352,6 +352,7 @@ kvm="auto" - hax="auto" - hvf="auto" - whpx="auto" -+nvmm="auto" - rdma="$default_feature" - pvrdma="$default_feature" - gprof="no" -@@ -1107,6 +1108,10 @@ for opt do - ;; - --enable-hvf) hvf="enabled" - ;; -+ --disable-nvmm) nvmm="disabled" -+ ;; -+ --enable-nvmm) nvmm="enabled" -+ ;; - --disable-whpx) whpx="disabled" - ;; - --enable-whpx) whpx="enabled" -@@ -1848,6 +1853,7 @@ disabled with --disable-FEATURE, default - kvm KVM acceleration support - hax HAX acceleration support - hvf Hypervisor.framework acceleration support -+ nvmm NVMM acceleration support - whpx Windows Hypervisor Platform acceleration support - rdma Enable RDMA-based migration - pvrdma Enable PVRDMA support -@@ -6410,7 +6416,7 @@ NINJA=$ninja $meson setup \ - -Db_coverage=$(if test "$gcov" = yes; then echo true; else echo false; fi) \ - -Db_lto=$lto -Dcfi=$cfi -Dcfi_debug=$cfi_debug \ - -Dmalloc=$malloc -Dmalloc_trim=$malloc_trim -Dsparse=$sparse \ -- -Dkvm=$kvm -Dhax=$hax -Dwhpx=$whpx -Dhvf=$hvf \ -+ -Dkvm=$kvm -Dhax=$hax -Dwhpx=$whpx -Dhvf=$hvf -Dnvmm=$nvmm \ - -Dxen=$xen -Dxen_pci_passthrough=$xen_pci_passthrough -Dtcg=$tcg \ - -Dcocoa=$cocoa -Dgtk=$gtk -Dmpath=$mpath -Dsdl=$sdl -Dsdl_image=$sdl_image \ - -Dvnc=$vnc -Dvnc_sasl=$vnc_sasl -Dvnc_jpeg=$vnc_jpeg -Dvnc_png=$vnc_png \ diff --git a/emulators/qemu/patches/patch-hw-mips-mipssim.c b/emulators/qemu/patches/patch-hw-mips-mipssim.c index c4e78130dfc..5782411eb63 100644 --- a/emulators/qemu/patches/patch-hw-mips-mipssim.c +++ b/emulators/qemu/patches/patch-hw-mips-mipssim.c @@ -1,8 +1,8 @@ -$NetBSD: patch-hw-mips-mipssim.c,v 1.3 2021/02/20 22:59:29 ryoon Exp $ +$NetBSD: patch-hw-mips-mipssim.c,v 1.4 2021/08/27 03:32:37 ryoon Exp $ ---- hw/mips/mipssim.c.orig 2020-12-08 16:59:44.000000000 +0000 +--- hw/mips/mipssim.c.orig 2021-08-04 16:29:07.000000000 +0000 +++ hw/mips/mipssim.c -@@ -39,6 +39,7 @@ +@@ -39,12 +39,20 @@ #include "hw/boards.h" #include "hw/mips/bios.h" #include "hw/loader.h" @@ -10,7 +10,6 @@ $NetBSD: patch-hw-mips-mipssim.c,v 1.3 2021/02/20 22:59:29 ryoon Exp $ #include "elf.h" #include "hw/sysbus.h" #include "hw/qdev-properties.h" -@@ -46,6 +47,13 @@ #include "qemu/error-report.h" #include "sysemu/qtest.h" #include "sysemu/reset.h" @@ -24,7 +23,7 @@ $NetBSD: patch-hw-mips-mipssim.c,v 1.3 2021/02/20 22:59:29 ryoon Exp $ static struct _loaderparams { int ram_size; -@@ -136,7 +144,7 @@ static void mipsnet_init(int base, qemu_ +@@ -135,7 +143,7 @@ static void mipsnet_init(int base, qemu_ sysbus_mmio_get_region(s, 0)); } @@ -33,7 +32,7 @@ $NetBSD: patch-hw-mips-mipssim.c,v 1.3 2021/02/20 22:59:29 ryoon Exp $ mips_mipssim_init(MachineState *machine) { const char *kernel_filename = machine->kernel_filename; -@@ -147,6 +155,7 @@ mips_mipssim_init(MachineState *machine) +@@ -146,6 +154,7 @@ mips_mipssim_init(MachineState *machine) MemoryRegion *isa = g_new(MemoryRegion, 1); MemoryRegion *bios = g_new(MemoryRegion, 1); Clock *cpuclk; @@ -41,7 +40,7 @@ $NetBSD: patch-hw-mips-mipssim.c,v 1.3 2021/02/20 22:59:29 ryoon Exp $ MIPSCPU *cpu; CPUMIPSState *env; ResetData *reset_info; -@@ -209,7 +218,7 @@ mips_mipssim_init(MachineState *machine) +@@ -208,7 +217,7 @@ mips_mipssim_init(MachineState *machine) /* Register 64 KB of ISA IO space at 0x1fd00000. */ memory_region_init_alias(isa, NULL, "isa_mmio", get_system_io(), 0, 0x00010000); @@ -50,7 +49,7 @@ $NetBSD: patch-hw-mips-mipssim.c,v 1.3 2021/02/20 22:59:29 ryoon Exp $ /* * A single 16450 sits at offset 0x3f8. It is attached to -@@ -230,6 +239,23 @@ mips_mipssim_init(MachineState *machine) +@@ -229,6 +238,23 @@ mips_mipssim_init(MachineState *machine) if (nd_table[0].used) /* MIPSnet uses the MIPS CPU INT0, which is interrupt 2. */ mipsnet_init(0x4200, env->irq[2], &nd_table[0]); diff --git a/emulators/qemu/patches/patch-hw_alpha_alpha_sys.h b/emulators/qemu/patches/patch-hw_alpha_alpha_sys.h deleted file mode 100644 index ae19d96f621..00000000000 --- a/emulators/qemu/patches/patch-hw_alpha_alpha_sys.h +++ /dev/null @@ -1,15 +0,0 @@ -$NetBSD: patch-hw_alpha_alpha_sys.h,v 1.1 2020/10/04 20:39:25 thorpej Exp $ - -Pass 'devfn_min' argument to typhoon_init(). - ---- hw/alpha/alpha_sys.h.orig 2020-10-01 00:17:37.231192966 +0000 -+++ hw/alpha/alpha_sys.h 2020-10-01 00:17:49.188425709 +0000 -@@ -11,7 +11,7 @@ - - - PCIBus *typhoon_init(MemoryRegion *, ISABus **, qemu_irq *, AlphaCPU *[4], -- pci_map_irq_fn); -+ pci_map_irq_fn, uint8_t devfn_min); - - /* alpha_pci.c. */ - extern const MemoryRegionOps alpha_pci_ignore_ops; diff --git a/emulators/qemu/patches/patch-hw_alpha_dp264.c b/emulators/qemu/patches/patch-hw_alpha_dp264.c deleted file mode 100644 index 1d3d99147a2..00000000000 --- a/emulators/qemu/patches/patch-hw_alpha_dp264.c +++ /dev/null @@ -1,39 +0,0 @@ -$NetBSD: patch-hw_alpha_dp264.c,v 1.1 2020/10/04 20:39:25 thorpej Exp $ - -Because we're using CLIPPER IRQ mappings, the minimum PCI device -IdSel is 1. Pass that to typhoon_init(). - -Set bit 6 in trap_arg2 to tell the PALcode that the -nographic option -was specified. This is used by the PALcode to initialize the CTB for -serial console. - ---- hw/alpha/dp264.c.orig 2020-08-11 19:17:14.000000000 +0000 -+++ hw/alpha/dp264.c 2020-10-02 15:52:10.654767858 +0000 -@@ -72,13 +72,25 @@ static void clipper_init(MachineState *m - cpus[i] = ALPHA_CPU(cpu_create(machine->cpu_type)); - } - -+ /* arg0 -> memory size -+ arg1 -> kernel entry point -+ arg2 -> config word -+ -+ Config word: bits 0-5 -> ncpus -+ bit 6 -> nographics option (for HWRPB CTB) -+ -+ See init_hwrpb() in the PALcode. */ -+ - cpus[0]->env.trap_arg0 = ram_size; - cpus[0]->env.trap_arg1 = 0; - cpus[0]->env.trap_arg2 = smp_cpus; -+ if (!machine->enable_graphics) -+ cpus[0]->env.trap_arg2 |= (1 << 6); - -- /* Init the chipset. */ -+ /* Init the chipset. Because we're using CLIPPER IRQ mappings, -+ the minimum PCI device IdSel is 1. */ - pci_bus = typhoon_init(machine->ram, &isa_bus, &rtc_irq, cpus, -- clipper_pci_map_irq); -+ clipper_pci_map_irq, PCI_DEVFN(1, 0)); - - /* Since we have an SRM-compatible PALcode, use the SRM epoch. */ - mc146818_rtc_init(isa_bus, 1900, rtc_irq); diff --git a/emulators/qemu/patches/patch-hw_alpha_typhoon.c b/emulators/qemu/patches/patch-hw_alpha_typhoon.c deleted file mode 100644 index a11679c5cc6..00000000000 --- a/emulators/qemu/patches/patch-hw_alpha_typhoon.c +++ /dev/null @@ -1,148 +0,0 @@ -$NetBSD: patch-hw_alpha_typhoon.c,v 1.1 2020/10/04 20:39:25 thorpej Exp $ - -Allow callers of typhoon_init() to specify a minimum PCI devfn. - -Add a minimal i82378 SIO PCI node so that NetBSD/alpha will find -and probe the ISA bus. - ---- hw/alpha/typhoon.c.orig 2020-10-01 00:34:35.392982214 +0000 -+++ hw/alpha/typhoon.c 2020-10-01 00:53:13.419539599 +0000 -@@ -817,7 +817,8 @@ static void typhoon_alarm_timer(void *op - } - - PCIBus *typhoon_init(MemoryRegion *ram, ISABus **isa_bus, qemu_irq *p_rtc_irq, -- AlphaCPU *cpus[4], pci_map_irq_fn sys_map_irq) -+ AlphaCPU *cpus[4], pci_map_irq_fn sys_map_irq, -+ uint8_t devfn_min) - { - MemoryRegion *addr_space = get_system_memory(); - DeviceState *dev; -@@ -887,7 +888,7 @@ PCIBus *typhoon_init(MemoryRegion *ram, - b = pci_register_root_bus(dev, "pci", - typhoon_set_irq, sys_map_irq, s, - &s->pchip.reg_mem, &s->pchip.reg_io, -- 0, 64, TYPE_PCI_BUS); -+ devfn_min, 64, TYPE_PCI_BUS); - phb->bus = b; - sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); - -@@ -921,10 +922,21 @@ PCIBus *typhoon_init(MemoryRegion *ram, - /* Pchip1 PCI configuration, 0x802.FE00.0000, 16MB. */ - - /* Init the ISA bus. */ -- /* ??? Technically there should be a cy82c693ub pci-isa bridge. */ -+ /* Init the PCI-ISA bridge. Technically, this would have been -+ a cy82c693ub, but a i82378 SIO was also used on many Alpha -+ systems and is close enough. -+ -+ ??? We are using a private, stripped down implementation of i82378 -+ so that we can handle the way the ISA interrupts are wired up on -+ Tsunami-type systems. We're leaving that (and the rest of the board -+ peripheral setup) untoucned; we merely need to instantiate the PCI -+ device node for the bridge, so that operating systems that expect -+ it to be there will see it. */ - { - qemu_irq *isa_irqs; - -+ pci_create_simple(b, PCI_DEVFN(7, 0), "i82378-typhoon"); -+ - *isa_bus = isa_bus_new(NULL, get_system_memory(), &s->pchip.reg_io, - &error_abort); - isa_irqs = i8259_init(*isa_bus, -@@ -955,10 +967,96 @@ static const TypeInfo typhoon_iommu_memo - .class_init = typhoon_iommu_memory_region_class_init, - }; - -+/* The following was copied from hw/isa/i82378.c and modified to provide -+ only the minimal PCI device node. */ -+ -+/* -+ * QEMU Intel i82378 emulation (PCI to ISA bridge) -+ * -+ * Copyright (c) 2010-2011 Herv\xc3\xa9 Poussineau -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, see <http://www.gnu.org/licenses/>. -+ */ -+ -+#include "migration/vmstate.h" -+ -+#define TYPE_I82378 "i82378-typhoon" -+#define I82378(obj) \ -+ OBJECT_CHECK(I82378State, (obj), TYPE_I82378) -+ -+typedef struct I82378State { -+ PCIDevice parent_obj; -+} I82378State; -+ -+static const VMStateDescription vmstate_i82378 = { -+ .name = "pci-i82378-typhoon", -+ .version_id = 0, -+ .minimum_version_id = 0, -+ .fields = (VMStateField[]) { -+ VMSTATE_PCI_DEVICE(parent_obj, I82378State), -+ VMSTATE_END_OF_LIST() -+ }, -+}; -+ -+static void i82378_realize(PCIDevice *pci, Error **errp) -+{ -+ uint8_t *pci_conf; -+ -+ pci_conf = pci->config; -+ pci_set_word(pci_conf + PCI_COMMAND, -+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); -+ pci_set_word(pci_conf + PCI_STATUS, -+ PCI_STATUS_DEVSEL_MEDIUM); -+ -+ pci_config_set_interrupt_pin(pci_conf, 1); /* interrupt pin 0 */ -+} -+ -+static void i82378_init(Object *obj) -+{ -+} -+ -+static void i82378_class_init(ObjectClass *klass, void *data) -+{ -+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); -+ DeviceClass *dc = DEVICE_CLASS(klass); -+ -+ k->realize = i82378_realize; -+ k->vendor_id = PCI_VENDOR_ID_INTEL; -+ k->device_id = PCI_DEVICE_ID_INTEL_82378; -+ k->revision = 0x03; -+ k->class_id = PCI_CLASS_BRIDGE_ISA; -+ dc->vmsd = &vmstate_i82378; -+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); -+} -+ -+static const TypeInfo i82378_typhoon_type_info = { -+ .name = TYPE_I82378, -+ .parent = TYPE_PCI_DEVICE, -+ .instance_size = sizeof(I82378State), -+ .instance_init = i82378_init, -+ .class_init = i82378_class_init, -+ .interfaces = (InterfaceInfo[]) { -+ { INTERFACE_CONVENTIONAL_PCI_DEVICE }, -+ { }, -+ }, -+}; -+ - static void typhoon_register_types(void) - { - type_register_static(&typhoon_pcihost_info); - type_register_static(&typhoon_iommu_memory_region_info); -+ type_register_static(&i82378_typhoon_type_info); - } - - type_init(typhoon_register_types) diff --git a/emulators/qemu/patches/patch-hw_mips_meson.build b/emulators/qemu/patches/patch-hw_mips_meson.build index a43c0bb9b6e..dc3c04567a2 100644 --- a/emulators/qemu/patches/patch-hw_mips_meson.build +++ b/emulators/qemu/patches/patch-hw_mips_meson.build @@ -1,13 +1,13 @@ -$NetBSD: patch-hw_mips_meson.build,v 1.2 2021/05/24 14:22:08 ryoon Exp $ +$NetBSD: patch-hw_mips_meson.build,v 1.3 2021/08/27 03:32:37 ryoon Exp $ ---- hw/mips/meson.build.orig 2021-04-29 17:18:58.000000000 +0000 +--- hw/mips/meson.build.orig 2021-08-04 16:29:07.000000000 +0000 +++ hw/mips/meson.build -@@ -5,7 +5,7 @@ mips_ss.add(when: 'CONFIG_FULOONG', if_t - mips_ss.add(when: 'CONFIG_LOONGSON3V', if_true: files('loongson3_bootp.c', 'loongson3_virt.c')) +@@ -7,7 +7,7 @@ mips_ss.add(when: 'CONFIG_MIPS_CPS', if_ + + if 'CONFIG_TCG' in config_all mips_ss.add(when: 'CONFIG_JAZZ', if_true: files('jazz.c')) - mips_ss.add(when: 'CONFIG_MALTA', if_true: files('gt64xxx_pci.c', 'malta.c')) -mips_ss.add(when: 'CONFIG_MIPSSIM', if_true: files('mipssim.c')) +mips_ss.add(when: 'CONFIG_MIPSSIM', if_true: files('mipssim.c', 'mipssim_virtio.c')) + mips_ss.add(when: 'CONFIG_FULOONG', if_true: files('fuloong2e.c')) mips_ss.add(when: 'CONFIG_MIPS_BOSTON', if_true: [files('boston.c'), fdt]) - mips_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('cps.c')) - + endif diff --git a/emulators/qemu/patches/patch-include_sysemu_hw__accel.h b/emulators/qemu/patches/patch-include_sysemu_hw__accel.h deleted file mode 100644 index 0d0cabfab7f..00000000000 --- a/emulators/qemu/patches/patch-include_sysemu_hw__accel.h +++ /dev/null @@ -1,12 +0,0 @@ -$NetBSD: patch-include_sysemu_hw__accel.h,v 1.4 2021/05/24 14:22:08 ryoon Exp $ - ---- include/sysemu/hw_accel.h.orig 2021-04-29 17:18:58.000000000 +0000 -+++ include/sysemu/hw_accel.h -@@ -16,6 +16,7 @@ - #include "sysemu/kvm.h" - #include "sysemu/hvf.h" - #include "sysemu/whpx.h" -+#include "sysemu/nvmm.h" - - void cpu_synchronize_state(CPUState *cpu); - void cpu_synchronize_post_reset(CPUState *cpu); diff --git a/emulators/qemu/patches/patch-include_sysemu_kvm.h b/emulators/qemu/patches/patch-include_sysemu_kvm.h deleted file mode 100644 index 3ea38887e3d..00000000000 --- a/emulators/qemu/patches/patch-include_sysemu_kvm.h +++ /dev/null @@ -1,23 +0,0 @@ -$NetBSD: patch-include_sysemu_kvm.h,v 1.2 2019/12/15 18:35:25 adam Exp $ - -Fix debug build on NetBSD (without Linux-KVM). - ---- include/sysemu/kvm.h.orig 2019-12-12 18:20:48.000000000 +0000 -+++ include/sysemu/kvm.h -@@ -465,8 +465,16 @@ int kvm_vm_check_extension(KVMState *s, - kvm_vcpu_ioctl(cpu, KVM_ENABLE_CAP, &cap); \ - }) - -+#ifdef CONFIG_KVM - uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function, - uint32_t index, int reg); -+#else -+#define kvm_arch_get_supported_cpuid(a,b,c,d) \ -+ ({ \ -+ abort(); \ -+ 0; \ -+ }) -+#endif - uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index); - - diff --git a/emulators/qemu/patches/patch-include_sysemu_nvmm.h b/emulators/qemu/patches/patch-include_sysemu_nvmm.h index cd5c1ca74cc..cb24fdb1e47 100644 --- a/emulators/qemu/patches/patch-include_sysemu_nvmm.h +++ b/emulators/qemu/patches/patch-include_sysemu_nvmm.h @@ -1,31 +1,33 @@ -$NetBSD: patch-include_sysemu_nvmm.h,v 1.4 2021/05/24 14:22:08 ryoon Exp $ +$NetBSD: patch-include_sysemu_nvmm.h,v 1.5 2021/08/27 03:32:37 ryoon Exp $ ---- include/sysemu/nvmm.h.orig 2021-05-06 04:47:40.186492405 +0000 +* Do not use CONFIG_NVMM directly to avoid pragma poison error. + +--- include/sysemu/nvmm.h.orig 2021-08-04 16:29:07.000000000 +0000 +++ include/sysemu/nvmm.h -@@ -0,0 +1,26 @@ -+/* -+ * Copyright (c) 2018-2019 Maxime Villard, All rights reserved. -+ * -+ * NetBSD Virtual Machine Monitor (NVMM) accelerator support. -+ * -+ * This work is licensed under the terms of the GNU GPL, version 2 or later. -+ * See the COPYING file in the top-level directory. -+ */ -+ -+#ifndef QEMU_NVMM_H -+#define QEMU_NVMM_H -+ -+#include "config-host.h" -+#include "qemu-common.h" -+ -+#ifdef CONFIG_NVMM -+ -+int nvmm_enabled(void); -+ -+#else /* CONFIG_NVMM */ -+ -+#define nvmm_enabled() (0) -+ -+#endif /* CONFIG_NVMM */ -+ -+#endif /* CONFIG_NVMM */ +@@ -13,14 +13,22 @@ + #include "config-host.h" + #include "qemu-common.h" + +-#ifdef CONFIG_NVMM ++#ifdef NEED_CPU_H ++# ifdef CONFIG_NVMM ++# define CONFIG_NVMM_IS_POSSIBLE ++# endif ++#else ++# define CONFIG_NVMM_IS_POSSIBLE ++#endif ++ ++#ifdef CONFIG_NVMM_IS_POSSIBLE + + int nvmm_enabled(void); + +-#else /* CONFIG_NVMM */ ++#else /* CONFIG_NVMM_IS_POSSIBLE */ + + #define nvmm_enabled() (0) + +-#endif /* CONFIG_NVMM */ ++#endif /* CONFIG_NVMM_IS_POSSIBLE */ + +-#endif /* CONFIG_NVMM */ ++#endif /* QEMU_NVMM_H */ diff --git a/emulators/qemu/patches/patch-meson.build b/emulators/qemu/patches/patch-meson.build index 4875d930ac7..00da5d79d6f 100644 --- a/emulators/qemu/patches/patch-meson.build +++ b/emulators/qemu/patches/patch-meson.build @@ -1,54 +1,22 @@ -$NetBSD: patch-meson.build,v 1.7 2021/07/09 21:08:33 schmonz Exp $ +$NetBSD: patch-meson.build,v 1.8 2021/08/27 03:32:37 ryoon Exp $ * Add NetBSD support. * Detect iconv in libc properly for pkgsrc (pkgsrc removes -liconv) to fix qemu-system-aarch64 link. * Detect curses (non-ncurses{,w} too) ---- meson.build.orig 2021-04-29 17:18:58.000000000 +0000 +--- meson.build.orig 2021-08-04 16:29:08.000000000 +0000 +++ meson.build -@@ -87,6 +87,7 @@ if cpu in ['x86', 'x86_64'] - accelerator_targets += { - 'CONFIG_HAX': ['i386-softmmu', 'x86_64-softmmu'], - 'CONFIG_HVF': ['x86_64-softmmu'], -+ 'CONFIG_NVMM': ['i386-softmmu', 'x86_64-softmmu'], - 'CONFIG_WHPX': ['i386-softmmu', 'x86_64-softmmu'], - } - endif -@@ -170,6 +171,7 @@ version_res = [] - coref = [] - iokit = [] - emulator_link_args = [] -+nvmm =not_found - hvf = not_found - if targetos == 'windows' - socket = cc.find_library('ws2_32') -@@ -227,6 +229,14 @@ if not get_option('hax').disabled() - accelerators += 'CONFIG_HAX' +@@ -237,7 +237,7 @@ if not get_option('hax').disabled() endif endif -+if targetos == 'netbsd' -+ if cc.has_header('nvmm.h', required: get_option('nvmm')) -+ nvmm = cc.find_library('nvmm', required: get_option('nvmm')) -+ endif -+ if nvmm.found() -+ accelerators += 'CONFIG_NVMM' -+ endif -+endif - - tcg_arch = config_host['ARCH'] - if not get_option('tcg').disabled() -@@ -271,6 +281,9 @@ endif - if 'CONFIG_HVF' not in accelerators and get_option('hvf').enabled() - error('HVF not available on this platform') - endif -+if 'CONFIG_NVMM' not in accelerators and get_option('nvmm').enabled() -+ error('NVMM not available on this platform') -+endif - if 'CONFIG_WHPX' not in accelerators and get_option('whpx').enabled() - error('WHPX not available on this platform') - endif -@@ -607,7 +620,7 @@ if have_system and not get_option('curse + if targetos == 'netbsd' +- if cc.has_header_symbol('nvmm.h', 'nvmm_cpu_stop', required: get_option('nvmm')) ++ if cc.has_header_symbol('nvmm.h', 'nvmm_vcpu_stop', required: get_option('nvmm')) + nvmm = cc.find_library('nvmm', required: get_option('nvmm')) + endif + if nvmm.found() +@@ -613,7 +613,7 @@ if have_system and not get_option('curse has_curses_h = cc.has_header('curses.h', args: curses_compile_args) endif if has_curses_h @@ -57,7 +25,7 @@ $NetBSD: patch-meson.build,v 1.7 2021/07/09 21:08:33 schmonz Exp $ foreach curses_libname : curses_libname_list libcurses = cc.find_library(curses_libname, required: false, -@@ -625,7 +638,7 @@ if have_system and not get_option('curse +@@ -631,7 +631,7 @@ if have_system and not get_option('curse endif endif if not get_option('iconv').disabled() @@ -66,19 +34,3 @@ $NetBSD: patch-meson.build,v 1.7 2021/07/09 21:08:33 schmonz Exp $ # Programs will be linked with glib and this will bring in libiconv on FreeBSD. # We need to use libiconv if available because mixing libiconv's headers with # the system libc does not work. -@@ -2129,6 +2142,7 @@ common_all = common_ss.apply(config_all, - common_all = static_library('common', - build_by_default: false, - sources: common_all.sources() + genh, -+ implicit_include_directories: false, - dependencies: common_all.dependencies(), - name_suffix: 'fa') - -@@ -2576,6 +2590,7 @@ if have_system - summary_info += {'HAX support': config_all.has_key('CONFIG_HAX')} - summary_info += {'HVF support': config_all.has_key('CONFIG_HVF')} - summary_info += {'WHPX support': config_all.has_key('CONFIG_WHPX')} -+ summary_info += {'NVMM support': config_all.has_key('CONFIG_NVMM')} - summary_info += {'Xen support': config_host.has_key('CONFIG_XEN_BACKEND')} - if config_host.has_key('CONFIG_XEN_BACKEND') - summary_info += {'xen ctrl version': config_host['CONFIG_XEN_CTRL_INTERFACE_VERSION']} diff --git a/emulators/qemu/patches/patch-meson__options.txt b/emulators/qemu/patches/patch-meson__options.txt deleted file mode 100644 index 8e951ef1446..00000000000 --- a/emulators/qemu/patches/patch-meson__options.txt +++ /dev/null @@ -1,13 +0,0 @@ -$NetBSD: patch-meson__options.txt,v 1.2 2021/05/24 14:22:08 ryoon Exp $ - ---- meson_options.txt.orig 2021-04-29 17:18:58.000000000 +0000 -+++ meson_options.txt -@@ -33,6 +33,8 @@ option('whpx', type: 'feature', value: ' - description: 'WHPX acceleration support') - option('hvf', type: 'feature', value: 'auto', - description: 'HVF acceleration support') -+option('nvmm', type: 'feature', value: 'auto', -+ description: 'NVMM acceleration support') - option('xen', type: 'feature', value: 'auto', - description: 'Xen backend support') - option('xen_pci_passthrough', type: 'feature', value: 'auto', diff --git a/emulators/qemu/patches/patch-nvmm-accel-ops.c b/emulators/qemu/patches/patch-nvmm-accel-ops.c deleted file mode 100644 index 9e14d316297..00000000000 --- a/emulators/qemu/patches/patch-nvmm-accel-ops.c +++ /dev/null @@ -1,116 +0,0 @@ -$NetBSD: patch-nvmm-accel-ops.c,v 1.1 2021/05/24 14:22:08 ryoon Exp $ - ---- nvmm-accel-ops.c.orig 2021-05-06 04:47:35.604520043 +0000 -+++ nvmm-accel-ops.c -@@ -0,0 +1,111 @@ -+/* -+ * Copyright (c) 2018-2019 Maxime Villard, All rights reserved. -+ * -+ * NetBSD Virtual Machine Monitor (NVMM) accelerator for QEMU. -+ * -+ * This work is licensed under the terms of the GNU GPL, version 2 or later. -+ * See the COPYING file in the top-level directory. -+ */ -+ -+#include "qemu/osdep.h" -+#include "sysemu/kvm_int.h" -+#include "qemu/main-loop.h" -+#include "sysemu/cpus.h" -+#include "qemu/guest-random.h" -+ -+#include "sysemu/nvmm.h" -+#include "nvmm-accel-ops.h" -+ -+static void *qemu_nvmm_cpu_thread_fn(void *arg) -+{ -+ CPUState *cpu = arg; -+ int r; -+ -+ assert(nvmm_enabled()); -+ -+ rcu_register_thread(); -+ -+ qemu_mutex_lock_iothread(); -+ qemu_thread_get_self(cpu->thread); -+ cpu->thread_id = qemu_get_thread_id(); -+ current_cpu = cpu; -+ -+ r = nvmm_init_vcpu(cpu); -+ if (r < 0) { -+ fprintf(stderr, "nvmm_init_vcpu failed: %s\n", strerror(-r)); -+ exit(1); -+ } -+ -+ /* signal CPU creation */ -+ cpu_thread_signal_created(cpu); -+ qemu_guest_random_seed_thread_part2(cpu->random_seed); -+ -+ do { -+ if (cpu_can_run(cpu)) { -+ r = nvmm_vcpu_exec(cpu); -+ if (r == EXCP_DEBUG) { -+ cpu_handle_guest_debug(cpu); -+ } -+ } -+ while (cpu_thread_is_idle(cpu)) { -+ qemu_cond_wait_iothread(cpu->halt_cond); -+ } -+ qemu_wait_io_event_common(cpu); -+ } while (!cpu->unplug || cpu_can_run(cpu)); -+ -+ nvmm_destroy_vcpu(cpu); -+ cpu_thread_signal_destroyed(cpu); -+ qemu_mutex_unlock_iothread(); -+ rcu_unregister_thread(); -+ return NULL; -+} -+ -+static void nvmm_start_vcpu_thread(CPUState *cpu) -+{ -+ char thread_name[VCPU_THREAD_NAME_SIZE]; -+ -+ cpu->thread = g_malloc0(sizeof(QemuThread)); -+ cpu->halt_cond = g_malloc0(sizeof(QemuCond)); -+ qemu_cond_init(cpu->halt_cond); -+ snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/NVMM", -+ cpu->cpu_index); -+ qemu_thread_create(cpu->thread, thread_name, qemu_nvmm_cpu_thread_fn, -+ cpu, QEMU_THREAD_JOINABLE); -+} -+ -+/* -+ * Abort the call to run the virtual processor by another thread, and to -+ * return the control to that thread. -+ */ -+static void nvmm_kick_vcpu_thread(CPUState *cpu) -+{ -+ cpu->exit_request = 1; -+ cpus_kick_thread(cpu); -+} -+ -+static void nvmm_accel_ops_class_init(ObjectClass *oc, void *data) -+{ -+ AccelOpsClass *ops = ACCEL_OPS_CLASS(oc); -+ -+ ops->create_vcpu_thread = nvmm_start_vcpu_thread; -+ ops->kick_vcpu_thread = nvmm_kick_vcpu_thread; -+ -+ ops->synchronize_post_reset = nvmm_cpu_synchronize_post_reset; -+ ops->synchronize_post_init = nvmm_cpu_synchronize_post_init; -+ ops->synchronize_state = nvmm_cpu_synchronize_state; -+ ops->synchronize_pre_loadvm = nvmm_cpu_synchronize_pre_loadvm; -+} -+ -+static const TypeInfo nvmm_accel_ops_type = { -+ .name = ACCEL_OPS_NAME("nvmm"), -+ -+ .parent = TYPE_ACCEL_OPS, -+ .class_init = nvmm_accel_ops_class_init, -+ .abstract = true, -+}; -+ -+static void nvmm_accel_ops_register_types(void) -+{ -+ type_register_static(&nvmm_accel_ops_type); -+} -+type_init(nvmm_accel_ops_register_types); diff --git a/emulators/qemu/patches/patch-nvmm-accel-ops.h b/emulators/qemu/patches/patch-nvmm-accel-ops.h deleted file mode 100644 index 2b73e5c68c0..00000000000 --- a/emulators/qemu/patches/patch-nvmm-accel-ops.h +++ /dev/null @@ -1,29 +0,0 @@ -$NetBSD: patch-nvmm-accel-ops.h,v 1.1 2021/05/24 14:22:08 ryoon Exp $ - ---- nvmm-accel-ops.h.orig 2021-05-06 04:47:35.605973012 +0000 -+++ nvmm-accel-ops.h -@@ -0,0 +1,24 @@ -+/* -+ * Copyright (c) 2018-2019 Maxime Villard, All rights reserved. -+ * -+ * NetBSD Virtual Machine Monitor (NVMM) accelerator for QEMU. -+ * -+ * This work is licensed under the terms of the GNU GPL, version 2 or later. -+ * See the COPYING file in the top-level directory. -+ */ -+ -+#ifndef NVMM_CPUS_H -+#define NVMM_CPUS_H -+ -+#include "sysemu/cpus.h" -+ -+int nvmm_init_vcpu(CPUState *cpu); -+int nvmm_vcpu_exec(CPUState *cpu); -+void nvmm_destroy_vcpu(CPUState *cpu); -+ -+void nvmm_cpu_synchronize_state(CPUState *cpu); -+void nvmm_cpu_synchronize_post_reset(CPUState *cpu); -+void nvmm_cpu_synchronize_post_init(CPUState *cpu); -+void nvmm_cpu_synchronize_pre_loadvm(CPUState *cpu); -+ -+#endif /* NVMM_CPUS_H */ diff --git a/emulators/qemu/patches/patch-nvmm-all.c b/emulators/qemu/patches/patch-nvmm-all.c deleted file mode 100644 index 4c4c1649d5a..00000000000 --- a/emulators/qemu/patches/patch-nvmm-all.c +++ /dev/null @@ -1,1231 +0,0 @@ -$NetBSD: patch-nvmm-all.c,v 1.1 2021/05/24 14:22:08 ryoon Exp $ - ---- nvmm-all.c.orig 2021-05-06 04:47:35.606086411 +0000 -+++ nvmm-all.c -@@ -0,0 +1,1226 @@ -+/* -+ * Copyright (c) 2018-2019 Maxime Villard, All rights reserved. -+ * -+ * NetBSD Virtual Machine Monitor (NVMM) accelerator for QEMU. -+ * -+ * This work is licensed under the terms of the GNU GPL, version 2 or later. -+ * See the COPYING file in the top-level directory. -+ */ -+ -+#include "qemu/osdep.h" -+#include "cpu.h" -+#include "exec/address-spaces.h" -+#include "exec/ioport.h" -+#include "qemu-common.h" -+#include "qemu/accel.h" -+#include "sysemu/nvmm.h" -+#include "sysemu/cpus.h" -+#include "sysemu/runstate.h" -+#include "qemu/main-loop.h" -+#include "qemu/error-report.h" -+#include "qapi/error.h" -+#include "qemu/queue.h" -+#include "migration/blocker.h" -+#include "strings.h" -+ -+#include "nvmm-accel-ops.h" -+ -+#include <nvmm.h> -+ -+struct qemu_vcpu { -+ struct nvmm_vcpu vcpu; -+ uint8_t tpr; -+ bool stop; -+ -+ /* Window-exiting for INTs/NMIs. */ -+ bool int_window_exit; -+ bool nmi_window_exit; -+ -+ /* The guest is in an interrupt shadow (POP SS, etc). */ -+ bool int_shadow; -+}; -+ -+struct qemu_machine { -+ struct nvmm_capability cap; -+ struct nvmm_machine mach; -+}; -+ -+/* -------------------------------------------------------------------------- */ -+ -+static bool nvmm_allowed; -+static struct qemu_machine qemu_mach; -+ -+static struct qemu_vcpu * -+get_qemu_vcpu(CPUState *cpu) -+{ -+ return (struct qemu_vcpu *)cpu->hax_vcpu; -+} -+ -+static struct nvmm_machine * -+get_nvmm_mach(void) -+{ -+ return &qemu_mach.mach; -+} -+ -+/* -------------------------------------------------------------------------- */ -+ -+static void -+nvmm_set_segment(struct nvmm_x64_state_seg *nseg, const SegmentCache *qseg) -+{ -+ uint32_t attrib = qseg->flags; -+ -+ nseg->selector = qseg->selector; -+ nseg->limit = qseg->limit; -+ nseg->base = qseg->base; -+ nseg->attrib.type = __SHIFTOUT(attrib, DESC_TYPE_MASK); -+ nseg->attrib.s = __SHIFTOUT(attrib, DESC_S_MASK); -+ nseg->attrib.dpl = __SHIFTOUT(attrib, DESC_DPL_MASK); -+ nseg->attrib.p = __SHIFTOUT(attrib, DESC_P_MASK); -+ nseg->attrib.avl = __SHIFTOUT(attrib, DESC_AVL_MASK); -+ nseg->attrib.l = __SHIFTOUT(attrib, DESC_L_MASK); -+ nseg->attrib.def = __SHIFTOUT(attrib, DESC_B_MASK); -+ nseg->attrib.g = __SHIFTOUT(attrib, DESC_G_MASK); -+} -+ -+static void -+nvmm_set_registers(CPUState *cpu) -+{ -+ struct CPUX86State *env = (CPUArchState *)cpu->env_ptr; -+ struct nvmm_machine *mach = get_nvmm_mach(); -+ struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu); -+ struct nvmm_vcpu *vcpu = &qcpu->vcpu; -+ struct nvmm_x64_state *state = vcpu->state; -+ uint64_t bitmap; -+ size_t i; -+ int ret; -+ -+ assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); -+ -+ /* GPRs. */ -+ state->gprs[NVMM_X64_GPR_RAX] = env->regs[R_EAX]; -+ state->gprs[NVMM_X64_GPR_RCX] = env->regs[R_ECX]; -+ state->gprs[NVMM_X64_GPR_RDX] = env->regs[R_EDX]; -+ state->gprs[NVMM_X64_GPR_RBX] = env->regs[R_EBX]; -+ state->gprs[NVMM_X64_GPR_RSP] = env->regs[R_ESP]; -+ state->gprs[NVMM_X64_GPR_RBP] = env->regs[R_EBP]; -+ state->gprs[NVMM_X64_GPR_RSI] = env->regs[R_ESI]; -+ state->gprs[NVMM_X64_GPR_RDI] = env->regs[R_EDI]; -+#ifdef TARGET_X86_64 -+ state->gprs[NVMM_X64_GPR_R8] = env->regs[R_R8]; -+ state->gprs[NVMM_X64_GPR_R9] = env->regs[R_R9]; -+ state->gprs[NVMM_X64_GPR_R10] = env->regs[R_R10]; -+ state->gprs[NVMM_X64_GPR_R11] = env->regs[R_R11]; -+ state->gprs[NVMM_X64_GPR_R12] = env->regs[R_R12]; -+ state->gprs[NVMM_X64_GPR_R13] = env->regs[R_R13]; -+ state->gprs[NVMM_X64_GPR_R14] = env->regs[R_R14]; -+ state->gprs[NVMM_X64_GPR_R15] = env->regs[R_R15]; -+#endif -+ -+ /* RIP and RFLAGS. */ -+ state->gprs[NVMM_X64_GPR_RIP] = env->eip; -+ state->gprs[NVMM_X64_GPR_RFLAGS] = env->eflags; -+ -+ /* Segments. */ -+ nvmm_set_segment(&state->segs[NVMM_X64_SEG_CS], &env->segs[R_CS]); -+ nvmm_set_segment(&state->segs[NVMM_X64_SEG_DS], &env->segs[R_DS]); -+ nvmm_set_segment(&state->segs[NVMM_X64_SEG_ES], &env->segs[R_ES]); -+ nvmm_set_segment(&state->segs[NVMM_X64_SEG_FS], &env->segs[R_FS]); -+ nvmm_set_segment(&state->segs[NVMM_X64_SEG_GS], &env->segs[R_GS]); -+ nvmm_set_segment(&state->segs[NVMM_X64_SEG_SS], &env->segs[R_SS]); -+ -+ /* Special segments. */ -+ nvmm_set_segment(&state->segs[NVMM_X64_SEG_GDT], &env->gdt); -+ nvmm_set_segment(&state->segs[NVMM_X64_SEG_LDT], &env->ldt); -+ nvmm_set_segment(&state->segs[NVMM_X64_SEG_TR], &env->tr); -+ nvmm_set_segment(&state->segs[NVMM_X64_SEG_IDT], &env->idt); -+ -+ /* Control registers. */ -+ state->crs[NVMM_X64_CR_CR0] = env->cr[0]; -+ state->crs[NVMM_X64_CR_CR2] = env->cr[2]; -+ state->crs[NVMM_X64_CR_CR3] = env->cr[3]; -+ state->crs[NVMM_X64_CR_CR4] = env->cr[4]; -+ state->crs[NVMM_X64_CR_CR8] = qcpu->tpr; -+ state->crs[NVMM_X64_CR_XCR0] = env->xcr0; -+ -+ /* Debug registers. */ -+ state->drs[NVMM_X64_DR_DR0] = env->dr[0]; -+ state->drs[NVMM_X64_DR_DR1] = env->dr[1]; -+ state->drs[NVMM_X64_DR_DR2] = env->dr[2]; -+ state->drs[NVMM_X64_DR_DR3] = env->dr[3]; -+ state->drs[NVMM_X64_DR_DR6] = env->dr[6]; -+ state->drs[NVMM_X64_DR_DR7] = env->dr[7]; -+ -+ /* FPU. */ -+ state->fpu.fx_cw = env->fpuc; -+ state->fpu.fx_sw = (env->fpus & ~0x3800) | ((env->fpstt & 0x7) << 11); -+ state->fpu.fx_tw = 0; -+ for (i = 0; i < 8; i++) { -+ state->fpu.fx_tw |= (!env->fptags[i]) << i; -+ } -+ state->fpu.fx_opcode = env->fpop; -+ state->fpu.fx_ip.fa_64 = env->fpip; -+ state->fpu.fx_dp.fa_64 = env->fpdp; -+ state->fpu.fx_mxcsr = env->mxcsr; -+ state->fpu.fx_mxcsr_mask = 0x0000FFFF; -+ assert(sizeof(state->fpu.fx_87_ac) == sizeof(env->fpregs)); -+ memcpy(state->fpu.fx_87_ac, env->fpregs, sizeof(env->fpregs)); -+ for (i = 0; i < CPU_NB_REGS; i++) { -+ memcpy(&state->fpu.fx_xmm[i].xmm_bytes[0], -+ &env->xmm_regs[i].ZMM_Q(0), 8); -+ memcpy(&state->fpu.fx_xmm[i].xmm_bytes[8], -+ &env->xmm_regs[i].ZMM_Q(1), 8); -+ } -+ -+ /* MSRs. */ -+ state->msrs[NVMM_X64_MSR_EFER] = env->efer; -+ state->msrs[NVMM_X64_MSR_STAR] = env->star; -+#ifdef TARGET_X86_64 -+ state->msrs[NVMM_X64_MSR_LSTAR] = env->lstar; -+ state->msrs[NVMM_X64_MSR_CSTAR] = env->cstar; -+ state->msrs[NVMM_X64_MSR_SFMASK] = env->fmask; -+ state->msrs[NVMM_X64_MSR_KERNELGSBASE] = env->kernelgsbase; -+#endif -+ state->msrs[NVMM_X64_MSR_SYSENTER_CS] = env->sysenter_cs; -+ state->msrs[NVMM_X64_MSR_SYSENTER_ESP] = env->sysenter_esp; -+ state->msrs[NVMM_X64_MSR_SYSENTER_EIP] = env->sysenter_eip; -+ state->msrs[NVMM_X64_MSR_PAT] = env->pat; -+ state->msrs[NVMM_X64_MSR_TSC] = env->tsc; -+ -+ bitmap = -+ NVMM_X64_STATE_SEGS | -+ NVMM_X64_STATE_GPRS | -+ NVMM_X64_STATE_CRS | -+ NVMM_X64_STATE_DRS | -+ NVMM_X64_STATE_MSRS | -+ NVMM_X64_STATE_FPU; -+ -+ ret = nvmm_vcpu_setstate(mach, vcpu, bitmap); -+ if (ret == -1) { -+ error_report("NVMM: Failed to set virtual processor context," -+ " error=%d", errno); -+ } -+} -+ -+static void -+nvmm_get_segment(SegmentCache *qseg, const struct nvmm_x64_state_seg *nseg) -+{ -+ qseg->selector = nseg->selector; -+ qseg->limit = nseg->limit; -+ qseg->base = nseg->base; -+ -+ qseg->flags = -+ __SHIFTIN((uint32_t)nseg->attrib.type, DESC_TYPE_MASK) | -+ __SHIFTIN((uint32_t)nseg->attrib.s, DESC_S_MASK) | -+ __SHIFTIN((uint32_t)nseg->attrib.dpl, DESC_DPL_MASK) | -+ __SHIFTIN((uint32_t)nseg->attrib.p, DESC_P_MASK) | -+ __SHIFTIN((uint32_t)nseg->attrib.avl, DESC_AVL_MASK) | -+ __SHIFTIN((uint32_t)nseg->attrib.l, DESC_L_MASK) | -+ __SHIFTIN((uint32_t)nseg->attrib.def, DESC_B_MASK) | -+ __SHIFTIN((uint32_t)nseg->attrib.g, DESC_G_MASK); -+} -+ -+static void -+nvmm_get_registers(CPUState *cpu) -+{ -+ struct CPUX86State *env = (CPUArchState *)cpu->env_ptr; -+ struct nvmm_machine *mach = get_nvmm_mach(); -+ struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu); -+ struct nvmm_vcpu *vcpu = &qcpu->vcpu; -+ X86CPU *x86_cpu = X86_CPU(cpu); -+ struct nvmm_x64_state *state = vcpu->state; -+ uint64_t bitmap, tpr; -+ size_t i; -+ int ret; -+ -+ assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); -+ -+ bitmap = -+ NVMM_X64_STATE_SEGS | -+ NVMM_X64_STATE_GPRS | -+ NVMM_X64_STATE_CRS | -+ NVMM_X64_STATE_DRS | -+ NVMM_X64_STATE_MSRS | -+ NVMM_X64_STATE_FPU; -+ -+ ret = nvmm_vcpu_getstate(mach, vcpu, bitmap); -+ if (ret == -1) { -+ error_report("NVMM: Failed to get virtual processor context," -+ " error=%d", errno); -+ } -+ -+ /* GPRs. */ -+ env->regs[R_EAX] = state->gprs[NVMM_X64_GPR_RAX]; -+ env->regs[R_ECX] = state->gprs[NVMM_X64_GPR_RCX]; -+ env->regs[R_EDX] = state->gprs[NVMM_X64_GPR_RDX]; -+ env->regs[R_EBX] = state->gprs[NVMM_X64_GPR_RBX]; -+ env->regs[R_ESP] = state->gprs[NVMM_X64_GPR_RSP]; -+ env->regs[R_EBP] = state->gprs[NVMM_X64_GPR_RBP]; -+ env->regs[R_ESI] = state->gprs[NVMM_X64_GPR_RSI]; -+ env->regs[R_EDI] = state->gprs[NVMM_X64_GPR_RDI]; -+#ifdef TARGET_X86_64 -+ env->regs[R_R8] = state->gprs[NVMM_X64_GPR_R8]; -+ env->regs[R_R9] = state->gprs[NVMM_X64_GPR_R9]; -+ env->regs[R_R10] = state->gprs[NVMM_X64_GPR_R10]; -+ env->regs[R_R11] = state->gprs[NVMM_X64_GPR_R11]; -+ env->regs[R_R12] = state->gprs[NVMM_X64_GPR_R12]; -+ env->regs[R_R13] = state->gprs[NVMM_X64_GPR_R13]; -+ env->regs[R_R14] = state->gprs[NVMM_X64_GPR_R14]; -+ env->regs[R_R15] = state->gprs[NVMM_X64_GPR_R15]; -+#endif -+ -+ /* RIP and RFLAGS. */ -+ env->eip = state->gprs[NVMM_X64_GPR_RIP]; -+ env->eflags = state->gprs[NVMM_X64_GPR_RFLAGS]; -+ -+ /* Segments. */ -+ nvmm_get_segment(&env->segs[R_ES], &state->segs[NVMM_X64_SEG_ES]); -+ nvmm_get_segment(&env->segs[R_CS], &state->segs[NVMM_X64_SEG_CS]); -+ nvmm_get_segment(&env->segs[R_SS], &state->segs[NVMM_X64_SEG_SS]); -+ nvmm_get_segment(&env->segs[R_DS], &state->segs[NVMM_X64_SEG_DS]); -+ nvmm_get_segment(&env->segs[R_FS], &state->segs[NVMM_X64_SEG_FS]); -+ nvmm_get_segment(&env->segs[R_GS], &state->segs[NVMM_X64_SEG_GS]); -+ -+ /* Special segments. */ -+ nvmm_get_segment(&env->gdt, &state->segs[NVMM_X64_SEG_GDT]); -+ nvmm_get_segment(&env->ldt, &state->segs[NVMM_X64_SEG_LDT]); -+ nvmm_get_segment(&env->tr, &state->segs[NVMM_X64_SEG_TR]); -+ nvmm_get_segment(&env->idt, &state->segs[NVMM_X64_SEG_IDT]); -+ -+ /* Control registers. */ -+ env->cr[0] = state->crs[NVMM_X64_CR_CR0]; -+ env->cr[2] = state->crs[NVMM_X64_CR_CR2]; -+ env->cr[3] = state->crs[NVMM_X64_CR_CR3]; -+ env->cr[4] = state->crs[NVMM_X64_CR_CR4]; -+ tpr = state->crs[NVMM_X64_CR_CR8]; -+ if (tpr != qcpu->tpr) { -+ qcpu->tpr = tpr; -+ cpu_set_apic_tpr(x86_cpu->apic_state, tpr); -+ } -+ env->xcr0 = state->crs[NVMM_X64_CR_XCR0]; -+ -+ /* Debug registers. */ -+ env->dr[0] = state->drs[NVMM_X64_DR_DR0]; -+ env->dr[1] = state->drs[NVMM_X64_DR_DR1]; -+ env->dr[2] = state->drs[NVMM_X64_DR_DR2]; -+ env->dr[3] = state->drs[NVMM_X64_DR_DR3]; -+ env->dr[6] = state->drs[NVMM_X64_DR_DR6]; -+ env->dr[7] = state->drs[NVMM_X64_DR_DR7]; -+ -+ /* FPU. */ -+ env->fpuc = state->fpu.fx_cw; -+ env->fpstt = (state->fpu.fx_sw >> 11) & 0x7; -+ env->fpus = state->fpu.fx_sw & ~0x3800; -+ for (i = 0; i < 8; i++) { -+ env->fptags[i] = !((state->fpu.fx_tw >> i) & 1); -+ } -+ env->fpop = state->fpu.fx_opcode; -+ env->fpip = state->fpu.fx_ip.fa_64; -+ env->fpdp = state->fpu.fx_dp.fa_64; -+ env->mxcsr = state->fpu.fx_mxcsr; -+ assert(sizeof(state->fpu.fx_87_ac) == sizeof(env->fpregs)); -+ memcpy(env->fpregs, state->fpu.fx_87_ac, sizeof(env->fpregs)); -+ for (i = 0; i < CPU_NB_REGS; i++) { -+ memcpy(&env->xmm_regs[i].ZMM_Q(0), -+ &state->fpu.fx_xmm[i].xmm_bytes[0], 8); -+ memcpy(&env->xmm_regs[i].ZMM_Q(1), -+ &state->fpu.fx_xmm[i].xmm_bytes[8], 8); -+ } -+ -+ /* MSRs. */ -+ env->efer = state->msrs[NVMM_X64_MSR_EFER]; -+ env->star = state->msrs[NVMM_X64_MSR_STAR]; -+#ifdef TARGET_X86_64 -+ env->lstar = state->msrs[NVMM_X64_MSR_LSTAR]; -+ env->cstar = state->msrs[NVMM_X64_MSR_CSTAR]; -+ env->fmask = state->msrs[NVMM_X64_MSR_SFMASK]; -+ env->kernelgsbase = state->msrs[NVMM_X64_MSR_KERNELGSBASE]; -+#endif -+ env->sysenter_cs = state->msrs[NVMM_X64_MSR_SYSENTER_CS]; -+ env->sysenter_esp = state->msrs[NVMM_X64_MSR_SYSENTER_ESP]; -+ env->sysenter_eip = state->msrs[NVMM_X64_MSR_SYSENTER_EIP]; -+ env->pat = state->msrs[NVMM_X64_MSR_PAT]; -+ env->tsc = state->msrs[NVMM_X64_MSR_TSC]; -+ -+ x86_update_hflags(env); -+} -+ -+static bool -+nvmm_can_take_int(CPUState *cpu) -+{ -+ struct CPUX86State *env = (CPUArchState *)cpu->env_ptr; -+ struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu); -+ struct nvmm_vcpu *vcpu = &qcpu->vcpu; -+ struct nvmm_machine *mach = get_nvmm_mach(); -+ -+ if (qcpu->int_window_exit) { -+ return false; -+ } -+ -+ if (qcpu->int_shadow || !(env->eflags & IF_MASK)) { -+ struct nvmm_x64_state *state = vcpu->state; -+ -+ /* Exit on interrupt window. */ -+ nvmm_vcpu_getstate(mach, vcpu, NVMM_X64_STATE_INTR); -+ state->intr.int_window_exiting = 1; -+ nvmm_vcpu_setstate(mach, vcpu, NVMM_X64_STATE_INTR); -+ -+ return false; -+ } -+ -+ return true; -+} -+ -+static bool -+nvmm_can_take_nmi(CPUState *cpu) -+{ -+ struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu); -+ -+ /* -+ * Contrary to INTs, NMIs always schedule an exit when they are -+ * completed. Therefore, if window-exiting is enabled, it means -+ * NMIs are blocked. -+ */ -+ if (qcpu->nmi_window_exit) { -+ return false; -+ } -+ -+ return true; -+} -+ -+/* -+ * Called before the VCPU is run. We inject events generated by the I/O -+ * thread, and synchronize the guest TPR. -+ */ -+static void -+nvmm_vcpu_pre_run(CPUState *cpu) -+{ -+ struct CPUX86State *env = (CPUArchState *)cpu->env_ptr; -+ struct nvmm_machine *mach = get_nvmm_mach(); -+ struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu); -+ struct nvmm_vcpu *vcpu = &qcpu->vcpu; -+ X86CPU *x86_cpu = X86_CPU(cpu); -+ struct nvmm_x64_state *state = vcpu->state; -+ struct nvmm_vcpu_event *event = vcpu->event; -+ bool has_event = false; -+ bool sync_tpr = false; -+ uint8_t tpr; -+ int ret; -+ -+ qemu_mutex_lock_iothread(); -+ -+ tpr = cpu_get_apic_tpr(x86_cpu->apic_state); -+ if (tpr != qcpu->tpr) { -+ qcpu->tpr = tpr; -+ sync_tpr = true; -+ } -+ -+ /* -+ * Force the VCPU out of its inner loop to process any INIT requests -+ * or commit pending TPR access. -+ */ -+ if (cpu->interrupt_request & (CPU_INTERRUPT_INIT | CPU_INTERRUPT_TPR)) { -+ cpu->exit_request = 1; -+ } -+ -+ if (!has_event && (cpu->interrupt_request & CPU_INTERRUPT_NMI)) { -+ if (nvmm_can_take_nmi(cpu)) { -+ cpu->interrupt_request &= ~CPU_INTERRUPT_NMI; -+ event->type = NVMM_VCPU_EVENT_INTR; -+ event->vector = 2; -+ has_event = true; -+ } -+ } -+ -+ if (!has_event && (cpu->interrupt_request & CPU_INTERRUPT_HARD)) { -+ if (nvmm_can_take_int(cpu)) { -+ cpu->interrupt_request &= ~CPU_INTERRUPT_HARD; -+ event->type = NVMM_VCPU_EVENT_INTR; -+ event->vector = cpu_get_pic_interrupt(env); -+ has_event = true; -+ } -+ } -+ -+ /* Don't want SMIs. */ -+ if (cpu->interrupt_request & CPU_INTERRUPT_SMI) { -+ cpu->interrupt_request &= ~CPU_INTERRUPT_SMI; -+ } -+ -+ if (sync_tpr) { -+ ret = nvmm_vcpu_getstate(mach, vcpu, NVMM_X64_STATE_CRS); -+ if (ret == -1) { -+ error_report("NVMM: Failed to get CPU state," -+ " error=%d", errno); -+ } -+ -+ state->crs[NVMM_X64_CR_CR8] = qcpu->tpr; -+ -+ ret = nvmm_vcpu_setstate(mach, vcpu, NVMM_X64_STATE_CRS); -+ if (ret == -1) { -+ error_report("NVMM: Failed to set CPU state," -+ " error=%d", errno); -+ } -+ } -+ -+ if (has_event) { -+ ret = nvmm_vcpu_inject(mach, vcpu); -+ if (ret == -1) { -+ error_report("NVMM: Failed to inject event," -+ " error=%d", errno); -+ } -+ } -+ -+ qemu_mutex_unlock_iothread(); -+} -+ -+/* -+ * Called after the VCPU ran. We synchronize the host view of the TPR and -+ * RFLAGS. -+ */ -+static void -+nvmm_vcpu_post_run(CPUState *cpu, struct nvmm_vcpu_exit *exit) -+{ -+ struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu); -+ struct CPUX86State *env = (CPUArchState *)cpu->env_ptr; -+ X86CPU *x86_cpu = X86_CPU(cpu); -+ uint64_t tpr; -+ -+ env->eflags = exit->exitstate.rflags; -+ qcpu->int_shadow = exit->exitstate.int_shadow; -+ qcpu->int_window_exit = exit->exitstate.int_window_exiting; -+ qcpu->nmi_window_exit = exit->exitstate.nmi_window_exiting; -+ -+ tpr = exit->exitstate.cr8; -+ if (qcpu->tpr != tpr) { -+ qcpu->tpr = tpr; -+ qemu_mutex_lock_iothread(); -+ cpu_set_apic_tpr(x86_cpu->apic_state, qcpu->tpr); -+ qemu_mutex_unlock_iothread(); -+ } -+} -+ -+/* -------------------------------------------------------------------------- */ -+ -+static void -+nvmm_io_callback(struct nvmm_io *io) -+{ -+ MemTxAttrs attrs = { 0 }; -+ int ret; -+ -+ ret = address_space_rw(&address_space_io, io->port, attrs, io->data, -+ io->size, !io->in); -+ if (ret != MEMTX_OK) { -+ error_report("NVMM: I/O Transaction Failed " -+ "[%s, port=%u, size=%zu]", (io->in ? "in" : "out"), -+ io->port, io->size); -+ } -+ -+ /* Needed, otherwise infinite loop. */ -+ current_cpu->vcpu_dirty = false; -+} -+ -+static void -+nvmm_mem_callback(struct nvmm_mem *mem) -+{ -+ cpu_physical_memory_rw(mem->gpa, mem->data, mem->size, mem->write); -+ -+ /* Needed, otherwise infinite loop. */ -+ current_cpu->vcpu_dirty = false; -+} -+ -+static struct nvmm_assist_callbacks nvmm_callbacks = { -+ .io = nvmm_io_callback, -+ .mem = nvmm_mem_callback -+}; -+ -+/* -------------------------------------------------------------------------- */ -+ -+static int -+nvmm_handle_mem(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) -+{ -+ int ret; -+ -+ ret = nvmm_assist_mem(mach, vcpu); -+ if (ret == -1) { -+ error_report("NVMM: Mem Assist Failed [gpa=%p]", -+ (void *)vcpu->exit->u.mem.gpa); -+ } -+ -+ return ret; -+} -+ -+static int -+nvmm_handle_io(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) -+{ -+ int ret; -+ -+ ret = nvmm_assist_io(mach, vcpu); -+ if (ret == -1) { -+ error_report("NVMM: I/O Assist Failed [port=%d]", -+ (int)vcpu->exit->u.io.port); -+ } -+ -+ return ret; -+} -+ -+static int -+nvmm_handle_rdmsr(struct nvmm_machine *mach, CPUState *cpu, -+ struct nvmm_vcpu_exit *exit) -+{ -+ struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu); -+ struct nvmm_vcpu *vcpu = &qcpu->vcpu; -+ X86CPU *x86_cpu = X86_CPU(cpu); -+ struct nvmm_x64_state *state = vcpu->state; -+ uint64_t val; -+ int ret; -+ -+ switch (exit->u.rdmsr.msr) { -+ case MSR_IA32_APICBASE: -+ val = cpu_get_apic_base(x86_cpu->apic_state); -+ break; -+ case MSR_MTRRcap: -+ case MSR_MTRRdefType: -+ case MSR_MCG_CAP: -+ case MSR_MCG_STATUS: -+ val = 0; -+ break; -+ default: /* More MSRs to add? */ -+ val = 0; -+ error_report("NVMM: Unexpected RDMSR 0x%x, ignored", -+ exit->u.rdmsr.msr); -+ break; -+ } -+ -+ ret = nvmm_vcpu_getstate(mach, vcpu, NVMM_X64_STATE_GPRS); -+ if (ret == -1) { -+ return -1; -+ } -+ -+ state->gprs[NVMM_X64_GPR_RAX] = (val & 0xFFFFFFFF); -+ state->gprs[NVMM_X64_GPR_RDX] = (val >> 32); -+ state->gprs[NVMM_X64_GPR_RIP] = exit->u.rdmsr.npc; -+ -+ ret = nvmm_vcpu_setstate(mach, vcpu, NVMM_X64_STATE_GPRS); -+ if (ret == -1) { -+ return -1; -+ } -+ -+ return 0; -+} -+ -+static int -+nvmm_handle_wrmsr(struct nvmm_machine *mach, CPUState *cpu, -+ struct nvmm_vcpu_exit *exit) -+{ -+ struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu); -+ struct nvmm_vcpu *vcpu = &qcpu->vcpu; -+ X86CPU *x86_cpu = X86_CPU(cpu); -+ struct nvmm_x64_state *state = vcpu->state; -+ uint64_t val; -+ int ret; -+ -+ val = exit->u.wrmsr.val; -+ -+ switch (exit->u.wrmsr.msr) { -+ case MSR_IA32_APICBASE: -+ cpu_set_apic_base(x86_cpu->apic_state, val); -+ break; -+ case MSR_MTRRdefType: -+ case MSR_MCG_STATUS: -+ break; -+ default: /* More MSRs to add? */ -+ error_report("NVMM: Unexpected WRMSR 0x%x [val=0x%lx], ignored", -+ exit->u.wrmsr.msr, val); -+ break; -+ } -+ -+ ret = nvmm_vcpu_getstate(mach, vcpu, NVMM_X64_STATE_GPRS); -+ if (ret == -1) { -+ return -1; -+ } -+ -+ state->gprs[NVMM_X64_GPR_RIP] = exit->u.wrmsr.npc; -+ -+ ret = nvmm_vcpu_setstate(mach, vcpu, NVMM_X64_STATE_GPRS); -+ if (ret == -1) { -+ return -1; -+ } -+ -+ return 0; -+} -+ -+static int -+nvmm_handle_halted(struct nvmm_machine *mach, CPUState *cpu, -+ struct nvmm_vcpu_exit *exit) -+{ -+ struct CPUX86State *env = (CPUArchState *)cpu->env_ptr; -+ int ret = 0; -+ -+ qemu_mutex_lock_iothread(); -+ -+ if (!((cpu->interrupt_request & CPU_INTERRUPT_HARD) && -+ (env->eflags & IF_MASK)) && -+ !(cpu->interrupt_request & CPU_INTERRUPT_NMI)) { -+ cpu->exception_index = EXCP_HLT; -+ cpu->halted = true; -+ ret = 1; -+ } -+ -+ qemu_mutex_unlock_iothread(); -+ -+ return ret; -+} -+ -+static int -+nvmm_inject_ud(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) -+{ -+ struct nvmm_vcpu_event *event = vcpu->event; -+ -+ event->type = NVMM_VCPU_EVENT_EXCP; -+ event->vector = 6; -+ event->u.excp.error = 0; -+ -+ return nvmm_vcpu_inject(mach, vcpu); -+} -+ -+static int -+nvmm_vcpu_loop(CPUState *cpu) -+{ -+ struct CPUX86State *env = (CPUArchState *)cpu->env_ptr; -+ struct nvmm_machine *mach = get_nvmm_mach(); -+ struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu); -+ struct nvmm_vcpu *vcpu = &qcpu->vcpu; -+ X86CPU *x86_cpu = X86_CPU(cpu); -+ struct nvmm_vcpu_exit *exit = vcpu->exit; -+ int ret; -+ -+ /* -+ * Some asynchronous events must be handled outside of the inner -+ * VCPU loop. They are handled here. -+ */ -+ if (cpu->interrupt_request & CPU_INTERRUPT_INIT) { -+ nvmm_cpu_synchronize_state(cpu); -+ do_cpu_init(x86_cpu); -+ /* set int/nmi windows back to the reset state */ -+ } -+ if (cpu->interrupt_request & CPU_INTERRUPT_POLL) { -+ cpu->interrupt_request &= ~CPU_INTERRUPT_POLL; -+ apic_poll_irq(x86_cpu->apic_state); -+ } -+ if (((cpu->interrupt_request & CPU_INTERRUPT_HARD) && -+ (env->eflags & IF_MASK)) || -+ (cpu->interrupt_request & CPU_INTERRUPT_NMI)) { -+ cpu->halted = false; -+ } -+ if (cpu->interrupt_request & CPU_INTERRUPT_SIPI) { -+ nvmm_cpu_synchronize_state(cpu); -+ do_cpu_sipi(x86_cpu); -+ } -+ if (cpu->interrupt_request & CPU_INTERRUPT_TPR) { -+ cpu->interrupt_request &= ~CPU_INTERRUPT_TPR; -+ nvmm_cpu_synchronize_state(cpu); -+ apic_handle_tpr_access_report(x86_cpu->apic_state, env->eip, -+ env->tpr_access_type); -+ } -+ -+ if (cpu->halted) { -+ cpu->exception_index = EXCP_HLT; -+ qatomic_set(&cpu->exit_request, false); -+ return 0; -+ } -+ -+ qemu_mutex_unlock_iothread(); -+ cpu_exec_start(cpu); -+ -+ /* -+ * Inner VCPU loop. -+ */ -+ do { -+ if (cpu->vcpu_dirty) { -+ nvmm_set_registers(cpu); -+ cpu->vcpu_dirty = false; -+ } -+ -+ if (qcpu->stop) { -+ cpu->exception_index = EXCP_INTERRUPT; -+ qcpu->stop = false; -+ ret = 1; -+ break; -+ } -+ -+ nvmm_vcpu_pre_run(cpu); -+ -+ if (qatomic_read(&cpu->exit_request)) { -+ nvmm_vcpu_stop(vcpu); -+ } -+ -+ /* Read exit_request before the kernel reads the immediate exit flag */ -+ smp_rmb(); -+ ret = nvmm_vcpu_run(mach, vcpu); -+ if (ret == -1) { -+ error_report("NVMM: Failed to exec a virtual processor," -+ " error=%d", errno); -+ break; -+ } -+ -+ nvmm_vcpu_post_run(cpu, exit); -+ -+ switch (exit->reason) { -+ case NVMM_VCPU_EXIT_NONE: -+ break; -+ case NVMM_VCPU_EXIT_STOPPED: -+ /* -+ * The kernel cleared the immediate exit flag; cpu->exit_request -+ * must be cleared after -+ */ -+ smp_wmb(); -+ qcpu->stop = true; -+ break; -+ case NVMM_VCPU_EXIT_MEMORY: -+ ret = nvmm_handle_mem(mach, vcpu); -+ break; -+ case NVMM_VCPU_EXIT_IO: -+ ret = nvmm_handle_io(mach, vcpu); -+ break; -+ case NVMM_VCPU_EXIT_INT_READY: -+ case NVMM_VCPU_EXIT_NMI_READY: -+ case NVMM_VCPU_EXIT_TPR_CHANGED: -+ break; -+ case NVMM_VCPU_EXIT_HALTED: -+ ret = nvmm_handle_halted(mach, cpu, exit); -+ break; -+ case NVMM_VCPU_EXIT_SHUTDOWN: -+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); -+ cpu->exception_index = EXCP_INTERRUPT; -+ ret = 1; -+ break; -+ case NVMM_VCPU_EXIT_RDMSR: -+ ret = nvmm_handle_rdmsr(mach, cpu, exit); -+ break; -+ case NVMM_VCPU_EXIT_WRMSR: -+ ret = nvmm_handle_wrmsr(mach, cpu, exit); -+ break; -+ case NVMM_VCPU_EXIT_MONITOR: -+ case NVMM_VCPU_EXIT_MWAIT: -+ ret = nvmm_inject_ud(mach, vcpu); -+ break; -+ default: -+ error_report("NVMM: Unexpected VM exit code 0x%lx [hw=0x%lx]", -+ exit->reason, exit->u.inv.hwcode); -+ nvmm_get_registers(cpu); -+ qemu_mutex_lock_iothread(); -+ qemu_system_guest_panicked(cpu_get_crash_info(cpu)); -+ qemu_mutex_unlock_iothread(); -+ ret = -1; -+ break; -+ } -+ } while (ret == 0); -+ -+ cpu_exec_end(cpu); -+ qemu_mutex_lock_iothread(); -+ -+ qatomic_set(&cpu->exit_request, false); -+ -+ return ret < 0; -+} -+ -+/* -------------------------------------------------------------------------- */ -+ -+static void -+do_nvmm_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg) -+{ -+ nvmm_get_registers(cpu); -+ cpu->vcpu_dirty = true; -+} -+ -+static void -+do_nvmm_cpu_synchronize_post_reset(CPUState *cpu, run_on_cpu_data arg) -+{ -+ nvmm_set_registers(cpu); -+ cpu->vcpu_dirty = false; -+} -+ -+static void -+do_nvmm_cpu_synchronize_post_init(CPUState *cpu, run_on_cpu_data arg) -+{ -+ nvmm_set_registers(cpu); -+ cpu->vcpu_dirty = false; -+} -+ -+static void -+do_nvmm_cpu_synchronize_pre_loadvm(CPUState *cpu, run_on_cpu_data arg) -+{ -+ cpu->vcpu_dirty = true; -+} -+ -+void nvmm_cpu_synchronize_state(CPUState *cpu) -+{ -+ if (!cpu->vcpu_dirty) { -+ run_on_cpu(cpu, do_nvmm_cpu_synchronize_state, RUN_ON_CPU_NULL); -+ } -+} -+ -+void nvmm_cpu_synchronize_post_reset(CPUState *cpu) -+{ -+ run_on_cpu(cpu, do_nvmm_cpu_synchronize_post_reset, RUN_ON_CPU_NULL); -+} -+ -+void nvmm_cpu_synchronize_post_init(CPUState *cpu) -+{ -+ run_on_cpu(cpu, do_nvmm_cpu_synchronize_post_init, RUN_ON_CPU_NULL); -+} -+ -+void nvmm_cpu_synchronize_pre_loadvm(CPUState *cpu) -+{ -+ run_on_cpu(cpu, do_nvmm_cpu_synchronize_pre_loadvm, RUN_ON_CPU_NULL); -+} -+ -+/* -------------------------------------------------------------------------- */ -+ -+static Error *nvmm_migration_blocker; -+ -+/* -+ * The nvmm_vcpu_stop() mechanism breaks races between entering the VMM -+ * and another thread signaling the vCPU thread to exit. -+ */ -+ -+static void -+nvmm_ipi_signal(int sigcpu) -+{ -+ if (current_cpu) { -+ struct qemu_vcpu *qcpu = get_qemu_vcpu(current_cpu); -+ struct nvmm_vcpu *vcpu = &qcpu->vcpu; -+ nvmm_vcpu_stop(vcpu); -+ } -+} -+ -+static void -+nvmm_init_cpu_signals(void) -+{ -+ struct sigaction sigact; -+ sigset_t set; -+ -+ /* Install the IPI handler. */ -+ memset(&sigact, 0, sizeof(sigact)); -+ sigact.sa_handler = nvmm_ipi_signal; -+ sigaction(SIG_IPI, &sigact, NULL); -+ -+ /* Allow IPIs on the current thread. */ -+ sigprocmask(SIG_BLOCK, NULL, &set); -+ sigdelset(&set, SIG_IPI); -+ pthread_sigmask(SIG_SETMASK, &set, NULL); -+} -+ -+int -+nvmm_init_vcpu(CPUState *cpu) -+{ -+ struct nvmm_machine *mach = get_nvmm_mach(); -+ struct nvmm_vcpu_conf_cpuid cpuid; -+ struct nvmm_vcpu_conf_tpr tpr; -+ Error *local_error = NULL; -+ struct qemu_vcpu *qcpu; -+ int ret, err; -+ -+ nvmm_init_cpu_signals(); -+ -+ if (nvmm_migration_blocker == NULL) { -+ error_setg(&nvmm_migration_blocker, -+ "NVMM: Migration not supported"); -+ -+ (void)migrate_add_blocker(nvmm_migration_blocker, &local_error); -+ if (local_error) { -+ error_report_err(local_error); -+ migrate_del_blocker(nvmm_migration_blocker); -+ error_free(nvmm_migration_blocker); -+ return -EINVAL; -+ } -+ } -+ -+ qcpu = g_malloc0(sizeof(*qcpu)); -+ if (qcpu == NULL) { -+ error_report("NVMM: Failed to allocate VCPU context."); -+ return -ENOMEM; -+ } -+ -+ ret = nvmm_vcpu_create(mach, cpu->cpu_index, &qcpu->vcpu); -+ if (ret == -1) { -+ err = errno; -+ error_report("NVMM: Failed to create a virtual processor," -+ " error=%d", err); -+ g_free(qcpu); -+ return -err; -+ } -+ -+ memset(&cpuid, 0, sizeof(cpuid)); -+ cpuid.mask = 1; -+ cpuid.leaf = 0x00000001; -+ cpuid.u.mask.set.edx = CPUID_MCE | CPUID_MCA | CPUID_MTRR; -+ ret = nvmm_vcpu_configure(mach, &qcpu->vcpu, NVMM_VCPU_CONF_CPUID, -+ &cpuid); -+ if (ret == -1) { -+ err = errno; -+ error_report("NVMM: Failed to configure a virtual processor," -+ " error=%d", err); -+ g_free(qcpu); -+ return -err; -+ } -+ -+ ret = nvmm_vcpu_configure(mach, &qcpu->vcpu, NVMM_VCPU_CONF_CALLBACKS, -+ &nvmm_callbacks); -+ if (ret == -1) { -+ err = errno; -+ error_report("NVMM: Failed to configure a virtual processor," -+ " error=%d", err); -+ g_free(qcpu); -+ return -err; -+ } -+ -+ if (qemu_mach.cap.arch.vcpu_conf_support & NVMM_CAP_ARCH_VCPU_CONF_TPR) { -+ memset(&tpr, 0, sizeof(tpr)); -+ tpr.exit_changed = 1; -+ ret = nvmm_vcpu_configure(mach, &qcpu->vcpu, NVMM_VCPU_CONF_TPR, &tpr); -+ if (ret == -1) { -+ err = errno; -+ error_report("NVMM: Failed to configure a virtual processor," -+ " error=%d", err); -+ g_free(qcpu); -+ return -err; -+ } -+ } -+ -+ cpu->vcpu_dirty = true; -+ cpu->hax_vcpu = (struct hax_vcpu_state *)qcpu; -+ -+ return 0; -+} -+ -+int -+nvmm_vcpu_exec(CPUState *cpu) -+{ -+ int ret, fatal; -+ -+ while (1) { -+ if (cpu->exception_index >= EXCP_INTERRUPT) { -+ ret = cpu->exception_index; -+ cpu->exception_index = -1; -+ break; -+ } -+ -+ fatal = nvmm_vcpu_loop(cpu); -+ -+ if (fatal) { -+ error_report("NVMM: Failed to execute a VCPU."); -+ abort(); -+ } -+ } -+ -+ return ret; -+} -+ -+void -+nvmm_destroy_vcpu(CPUState *cpu) -+{ -+ struct nvmm_machine *mach = get_nvmm_mach(); -+ struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu); -+ -+ nvmm_vcpu_destroy(mach, &qcpu->vcpu); -+ g_free(cpu->hax_vcpu); -+} -+ -+/* -------------------------------------------------------------------------- */ -+ -+static void -+nvmm_update_mapping(hwaddr start_pa, ram_addr_t size, uintptr_t hva, -+ bool add, bool rom, const char *name) -+{ -+ struct nvmm_machine *mach = get_nvmm_mach(); -+ int ret, prot; -+ -+ if (add) { -+ prot = PROT_READ | PROT_EXEC; -+ if (!rom) { -+ prot |= PROT_WRITE; -+ } -+ ret = nvmm_gpa_map(mach, hva, start_pa, size, prot); -+ } else { -+ ret = nvmm_gpa_unmap(mach, hva, start_pa, size); -+ } -+ -+ if (ret == -1) { -+ error_report("NVMM: Failed to %s GPA range '%s' PA:%p, " -+ "Size:%p bytes, HostVA:%p, error=%d", -+ (add ? "map" : "unmap"), name, (void *)(uintptr_t)start_pa, -+ (void *)size, (void *)hva, errno); -+ } -+} -+ -+static void -+nvmm_process_section(MemoryRegionSection *section, int add) -+{ -+ MemoryRegion *mr = section->mr; -+ hwaddr start_pa = section->offset_within_address_space; -+ ram_addr_t size = int128_get64(section->size); -+ unsigned int delta; -+ uintptr_t hva; -+ -+ if (!memory_region_is_ram(mr)) { -+ return; -+ } -+ -+ /* Adjust start_pa and size so that they are page-aligned. */ -+ delta = qemu_real_host_page_size - (start_pa & ~qemu_real_host_page_mask); -+ delta &= ~qemu_real_host_page_mask; -+ if (delta > size) { -+ return; -+ } -+ start_pa += delta; -+ size -= delta; -+ size &= qemu_real_host_page_mask; -+ if (!size || (start_pa & ~qemu_real_host_page_mask)) { -+ return; -+ } -+ -+ hva = (uintptr_t)memory_region_get_ram_ptr(mr) + -+ section->offset_within_region + delta; -+ -+ nvmm_update_mapping(start_pa, size, hva, add, -+ memory_region_is_rom(mr), mr->name); -+} -+ -+static void -+nvmm_region_add(MemoryListener *listener, MemoryRegionSection *section) -+{ -+ memory_region_ref(section->mr); -+ nvmm_process_section(section, 1); -+} -+ -+static void -+nvmm_region_del(MemoryListener *listener, MemoryRegionSection *section) -+{ -+ nvmm_process_section(section, 0); -+ memory_region_unref(section->mr); -+} -+ -+static void -+nvmm_transaction_begin(MemoryListener *listener) -+{ -+ /* nothing */ -+} -+ -+static void -+nvmm_transaction_commit(MemoryListener *listener) -+{ -+ /* nothing */ -+} -+ -+static void -+nvmm_log_sync(MemoryListener *listener, MemoryRegionSection *section) -+{ -+ MemoryRegion *mr = section->mr; -+ -+ if (!memory_region_is_ram(mr)) { -+ return; -+ } -+ -+ memory_region_set_dirty(mr, 0, int128_get64(section->size)); -+} -+ -+static MemoryListener nvmm_memory_listener = { -+ .begin = nvmm_transaction_begin, -+ .commit = nvmm_transaction_commit, -+ .region_add = nvmm_region_add, -+ .region_del = nvmm_region_del, -+ .log_sync = nvmm_log_sync, -+ .priority = 10, -+}; -+ -+static void -+nvmm_ram_block_added(RAMBlockNotifier *n, void *host, size_t size) -+{ -+ struct nvmm_machine *mach = get_nvmm_mach(); -+ uintptr_t hva = (uintptr_t)host; -+ int ret; -+ -+ ret = nvmm_hva_map(mach, hva, size); -+ -+ if (ret == -1) { -+ error_report("NVMM: Failed to map HVA, HostVA:%p " -+ "Size:%p bytes, error=%d", -+ (void *)hva, (void *)size, errno); -+ } -+} -+ -+static struct RAMBlockNotifier nvmm_ram_notifier = { -+ .ram_block_added = nvmm_ram_block_added -+}; -+ -+/* -------------------------------------------------------------------------- */ -+ -+static int -+nvmm_accel_init(MachineState *ms) -+{ -+ int ret, err; -+ -+ ret = nvmm_init(); -+ if (ret == -1) { -+ err = errno; -+ error_report("NVMM: Initialization failed, error=%d", errno); -+ return -err; -+ } -+ -+ ret = nvmm_capability(&qemu_mach.cap); -+ if (ret == -1) { -+ err = errno; -+ error_report("NVMM: Unable to fetch capability, error=%d", errno); -+ return -err; -+ } -+ if (qemu_mach.cap.version < NVMM_KERN_VERSION) { -+ error_report("NVMM: Unsupported version %u", qemu_mach.cap.version); -+ return -EPROGMISMATCH; -+ } -+ if (qemu_mach.cap.state_size != sizeof(struct nvmm_x64_state)) { -+ error_report("NVMM: Wrong state size %u", qemu_mach.cap.state_size); -+ return -EPROGMISMATCH; -+ } -+ -+ ret = nvmm_machine_create(&qemu_mach.mach); -+ if (ret == -1) { -+ err = errno; -+ error_report("NVMM: Machine creation failed, error=%d", errno); -+ return -err; -+ } -+ -+ memory_listener_register(&nvmm_memory_listener, &address_space_memory); -+ ram_block_notifier_add(&nvmm_ram_notifier); -+ -+ printf("NetBSD Virtual Machine Monitor accelerator is operational\n"); -+ return 0; -+} -+ -+int -+nvmm_enabled(void) -+{ -+ return nvmm_allowed; -+} -+ -+static void -+nvmm_accel_class_init(ObjectClass *oc, void *data) -+{ -+ AccelClass *ac = ACCEL_CLASS(oc); -+ ac->name = "NVMM"; -+ ac->init_machine = nvmm_accel_init; -+ ac->allowed = &nvmm_allowed; -+} -+ -+static const TypeInfo nvmm_accel_type = { -+ .name = ACCEL_CLASS_NAME("nvmm"), -+ .parent = TYPE_ACCEL, -+ .class_init = nvmm_accel_class_init, -+}; -+ -+static void -+nvmm_type_init(void) -+{ -+ type_register_static(&nvmm_accel_type); -+} -+ -+type_init(nvmm_type_init); diff --git a/emulators/qemu/patches/patch-qemu-options.hx b/emulators/qemu/patches/patch-qemu-options.hx deleted file mode 100644 index 29e4702ae50..00000000000 --- a/emulators/qemu/patches/patch-qemu-options.hx +++ /dev/null @@ -1,40 +0,0 @@ -$NetBSD: patch-qemu-options.hx,v 1.5 2021/05/24 14:22:08 ryoon Exp $ - ---- qemu-options.hx.orig 2021-04-29 17:18:59.000000000 +0000 -+++ qemu-options.hx -@@ -26,7 +26,7 @@ DEF("machine", HAS_ARG, QEMU_OPTION_mach - "-machine [type=]name[,prop[=value][,...]]\n" - " selects emulated machine ('-machine help' for list)\n" - " property accel=accel1[:accel2[:...]] selects accelerator\n" -- " supported accelerators are kvm, xen, hax, hvf, whpx or tcg (default: tcg)\n" -+ " supported accelerators are kvm, xen, hax, hvf, nvmm, whpx or tcg (default: tcg)\n" - " vmport=on|off|auto controls emulation of vmport (default: auto)\n" - " dump-guest-core=on|off include guest memory in a core dump (default=on)\n" - " mem-merge=on|off controls memory merge support (default: on)\n" -@@ -58,7 +58,7 @@ SRST - - ``accel=accels1[:accels2[:...]]`` - This is used to enable an accelerator. Depending on the target -- architecture, kvm, xen, hax, hvf, whpx or tcg can be available. -+ architecture, kvm, xen, hax, hvf, nvmm, whpx or tcg can be available. - By default, tcg is used. If there is more than one accelerator - specified, the next one is used if the previous one fails to - initialize. -@@ -135,7 +135,7 @@ ERST - - DEF("accel", HAS_ARG, QEMU_OPTION_accel, - "-accel [accel=]accelerator[,prop[=value][,...]]\n" -- " select accelerator (kvm, xen, hax, hvf, whpx or tcg; use 'help' for a list)\n" -+ " select accelerator (kvm, xen, hax, hvf, nvmm, whpx or tcg; use 'help' for a list)\n" - " igd-passthru=on|off (enable Xen integrated Intel graphics passthrough, default=off)\n" - " kernel-irqchip=on|off|split controls accelerated irqchip support (default=on)\n" - " kvm-shadow-mem=size of KVM shadow MMU in bytes\n" -@@ -145,7 +145,7 @@ DEF("accel", HAS_ARG, QEMU_OPTION_accel, - SRST - ``-accel name[,prop=value[,...]]`` - This is used to enable an accelerator. Depending on the target -- architecture, kvm, xen, hax, hvf, whpx or tcg can be available. By -+ architecture, kvm, xen, hax, hvf, nvmm, whpx or tcg can be available. By - default, tcg is used. If there is more than one accelerator - specified, the next one is used if the previous one fails to - initialize. diff --git a/emulators/qemu/patches/patch-roms_qemu-palcode_hwrpb.h b/emulators/qemu/patches/patch-roms_qemu-palcode_hwrpb.h deleted file mode 100644 index 58bf04b8cb6..00000000000 --- a/emulators/qemu/patches/patch-roms_qemu-palcode_hwrpb.h +++ /dev/null @@ -1,72 +0,0 @@ -$NetBSD: patch-roms_qemu-palcode_hwrpb.h,v 1.1 2020/10/04 20:39:25 thorpej Exp $ - -Add definitions for the Console Terminal Block portion of the HWRPB. - ---- roms/qemu-palcode/hwrpb.h.orig 2020-10-03 23:04:51.494017689 +0000 -+++ roms/qemu-palcode/hwrpb.h 2020-10-03 23:06:34.713833960 +0000 -@@ -146,6 +146,65 @@ struct crb_struct { - struct vf_map_struct map[1]; - }; - -+struct ctb_struct { -+ unsigned long type; -+ unsigned long unit; -+ unsigned long res0; -+ unsigned long len; -+ unsigned long ipl; -+ unsigned long tintr_vec; -+ unsigned long rintr_vec; -+ unsigned long term_type; -+ unsigned long keybd_type; -+ unsigned long keybd_trans; -+ unsigned long keybd_map; -+ unsigned long keybd_state; -+ unsigned long keybd_last; -+ unsigned long font_us; -+ unsigned long font_mcs; -+ unsigned long font_width; -+ unsigned long font_height; -+ unsigned long mon_width; -+ unsigned long mon_height; -+ unsigned long dpi; -+ unsigned long planes; -+ unsigned long cur_width; -+ unsigned long cur_height; -+ unsigned long head_cnt; -+ unsigned long opwindow; -+ unsigned long head_offset; -+ unsigned long putchar; -+ unsigned long io_state; -+ unsigned long listen_state; -+ unsigned long xaddr; -+ unsigned long turboslot; -+ unsigned long server_off; -+ unsigned long line_off; -+ unsigned char csd; -+}; -+ -+#define CTB_NONE 0x00 -+#define CTB_PRINTERPORT 0x02 -+#define CTB_GRAPHICS 0x03 -+#define CTB_TYPE4 0x04 -+ -+/* -+ * Format of the Console Terminal Block Type 4 `turboslot' field: -+ * -+ * 63 40 39 32 31 24 23 16 15 8 7 0 -+ * | reserved | channel | hose | bus type | bus | slot| -+ */ -+#define CTB_TURBOSLOT_CHANNEL(x) (((x) >> 32) & 0xff) -+#define CTB_TURBOSLOT_HOSE(x) (((x) >> 24) & 0xff) -+#define CTB_TURBOSLOT_TYPE(x) (((x) >> 16) & 0xff) -+#define CTB_TURBOSLOT_BUS(x) (((x) >> 8) & 0xff) -+#define CTB_TURBOSLOT_SLOT(x) ((x) & 0xff) -+ -+#define CTB_TURBOSLOT_TYPE_TC 0 /* TURBOchannel */ -+#define CTB_TURBOSLOT_TYPE_ISA 1 /* ISA */ -+#define CTB_TURBOSLOT_TYPE_EISA 2 /* EISA */ -+#define CTB_TURBOSLOT_TYPE_PCI 3 /* PCI */ -+ - struct memclust_struct { - unsigned long start_pfn; - unsigned long numpages; diff --git a/emulators/qemu/patches/patch-roms_qemu-palcode_init.c b/emulators/qemu/patches/patch-roms_qemu-palcode_init.c deleted file mode 100644 index 5e39958a7b2..00000000000 --- a/emulators/qemu/patches/patch-roms_qemu-palcode_init.c +++ /dev/null @@ -1,234 +0,0 @@ -$NetBSD: patch-roms_qemu-palcode_init.c,v 1.1 2020/10/04 20:39:25 thorpej Exp $ - -- Don't include cross-host header files. -- Initialize the HWRPB CPU ID field with the WHAMI of the primary - CPU (and not the CPU type) as per the architecture specification. -- Don't set the "PALcode memory valid" bit in the PCS flags; that field - in the HWRPB is not initialized by this PALcode. -- Provide a Console Terminal Block (CTB) in the HWRPB - NetBSD requires - it to find the console device. -- Define entry point register $a2 as a config word, rather than just a - CPU count, and extract the "-nographic" option passed by Qemu, so that - the CTB can be initialized properly. -- Call the SWPPAL with a private argument in $a4, to specify the value of - $pv is to be after the SWPPAL has completed. -- When a secondary CPU starts up, extract a new value for $pv from the - HWRPB "CPU restart data" field, and pass that to the SWPPAL operation - used to trampiline to into the kernel entry point. - ---- roms/qemu-palcode/init.c.orig 2020-10-03 23:12:30.442663290 +0000 -+++ roms/qemu-palcode/init.c 2020-10-03 23:12:34.687159989 +0000 -@@ -18,8 +18,6 @@ - along with this program; see the file COPYING. If not see - <http://www.gnu.org/licenses/>. */ - --#include <string.h> --#include <stddef.h> - #include "hwrpb.h" - #include "osf.h" - #include "ioport.h" -@@ -38,11 +36,21 @@ - - #define HZ 1024 - -+/* -+ * Register a2 contains configuration information from the VM: -+ * -+ * bits 0-5 -- ncpus -+ * bit 6 -- "nographics" option -+ */ -+#define CONFIG_NCPUS(x) ((x) & 63) -+#define CONFIG_NOGRAPHICS(x) ((x) & (1ull << 6)) -+ - struct hwrpb_combine { - struct hwrpb_struct hwrpb; - struct percpu_struct processor[4]; - struct memdesc_struct md; - struct memclust_struct mc[2]; -+ struct ctb_struct ctb; - struct crb_struct crb; - struct procdesc_struct proc_dispatch; - struct procdesc_struct proc_fixup; -@@ -61,6 +69,8 @@ struct hwrpb_combine hwrpb __attribute__ - - void *last_alloc; - bool have_vga; -+unsigned int pci_vga_bus; -+unsigned int pci_vga_dev; - - static void * - alloc (unsigned long size, unsigned long align) -@@ -138,11 +148,13 @@ init_page_table(void) - } - - static void --init_hwrpb (unsigned long memsize, unsigned long cpus) -+init_hwrpb (unsigned long memsize, unsigned long config) - { - unsigned long pal_pages; - unsigned long amask; - unsigned long i; -+ unsigned long proc_type = EV4_CPU; -+ unsigned long cpus = CONFIG_NCPUS(config); - - hwrpb.hwrpb.phys_addr = PA(&hwrpb); - -@@ -164,12 +176,12 @@ init_hwrpb (unsigned long memsize, unsig - switch (__builtin_alpha_implver()) - { - case 0: /* EV4 */ -- hwrpb.hwrpb.cpuid = EV4_CPU; -+ proc_type = EV4_CPU; - hwrpb.hwrpb.max_asn = 63; - break; - - case 1: /* EV5 */ -- hwrpb.hwrpb.cpuid -+ proc_type - = ((amask & 0x101) == 0x101 ? PCA56_CPU /* MAX+BWX */ - : amask & 1 ? EV56_CPU /* BWX */ - : EV5_CPU); -@@ -177,11 +189,12 @@ init_hwrpb (unsigned long memsize, unsig - break; - - case 2: /* EV6 */ -- hwrpb.hwrpb.cpuid = (amask & 4 ? EV67_CPU : EV6_CPU); /* CIX */ -+ proc_type = (amask & 4 ? EV67_CPU : EV6_CPU); /* CIX */ - hwrpb.hwrpb.max_asn = 255; - break; - } - -+ hwrpb.hwrpb.cpuid = 0; /* CPU #0 is the primary */ - hwrpb.hwrpb.pagesize = PAGE_SIZE; - hwrpb.hwrpb.pa_bits = 40; - hwrpb.hwrpb.sys_type = SYS_TYPE; -@@ -189,9 +202,20 @@ init_hwrpb (unsigned long memsize, unsig - hwrpb.hwrpb.sys_revision = SYS_REVISION; - for (i = 0; i < cpus; ++i) - { -- /* ??? Look up these bits. Snagging the value examined by the kernel. */ -- hwrpb.processor[i].flags = 0x1cc; -- hwrpb.processor[i].type = hwrpb.hwrpb.cpuid; -+ /* -+ * original value was 0x1cc == -+ * PALcode loaded (0x100) -+ * PALcode memory valid (0x080) -+ * PALcode valid (0x040) -+ * processor present (0x008) -+ * processor available (0x004) -+ * -+ * Don't set PALcode memory valid -- we don't initialize those PCS -+ * fields! -+ */ -+ hwrpb.processor[i].flags = 0x14c; -+ hwrpb.processor[i].type = proc_type; -+ /* XXX hwrpb.processor[i].pal_revision */ - } - - hwrpb.hwrpb.intr_freq = HZ * 4096; -@@ -213,6 +237,21 @@ init_hwrpb (unsigned long memsize, unsig - hwrpb.mc[1].start_pfn = pal_pages; - hwrpb.mc[1].numpages = (memsize >> PAGE_SHIFT) - pal_pages; - -+ hwrpb.hwrpb.ctbt_offset = offsetof(struct hwrpb_combine, ctb); -+ hwrpb.hwrpb.ctb_size = sizeof(hwrpb.ctb); -+ if (have_vga && !CONFIG_NOGRAPHICS(config)) -+ { -+ printf("CTB: GRAPHICS PCI BUS %d DEV %d\r\n", pci_vga_bus, pci_vga_dev); -+ hwrpb.ctb.term_type = CTB_GRAPHICS; -+ hwrpb.ctb.turboslot = (CTB_TURBOSLOT_TYPE_PCI << 16) | -+ (pci_vga_bus << 8) | pci_vga_dev; -+ } -+ else -+ { -+ printf("CTB: PRINTERPORT\r\n"); -+ hwrpb.ctb.term_type = CTB_PRINTERPORT; -+ } -+ - hwrpb.hwrpb.crb_offset = offsetof(struct hwrpb_combine, crb); - hwrpb.crb.dispatch_va = &hwrpb.proc_dispatch; - hwrpb.crb.dispatch_pa = PA(&hwrpb.proc_dispatch); -@@ -260,7 +299,7 @@ init_i8259 (void) - outb(0x01, PORT_PIC1_DATA); /* ICW4 */ - - /* Initialize level triggers. The CY82C693UB that's on real alpha -- hardware doesn't have this; this is a PIIX extension. However, -+ hardware controls these differently; we assume a PIIX here. However, - QEMU doesn't implement regular level triggers. */ - outb(0xff, PORT_PIC2_ELCR); - outb(0xff, PORT_PIC1_ELCR); -@@ -275,32 +314,37 @@ init_i8259 (void) - } - - static void __attribute__((noreturn)) --swppal(void *entry, void *pcb) -+swppal(void *entry, void *pcb, unsigned long vptptr, unsigned long pv) - { - register int variant __asm__("$16") = 2; /* OSF/1 PALcode */ - register void *pc __asm__("$17") = entry; - register unsigned long pa_pcb __asm__("$18") = PA(pcb); -- register unsigned long vptptr __asm__("$19") = VPTPTR; -+ register unsigned long newvptptr __asm__("$19") = vptptr; -+ register unsigned long newpv __asm__("$20") = pv; - -- asm("call_pal 0x0a" : : "r"(variant), "r"(pc), "r"(pa_pcb), "r"(vptptr)); -+ asm("call_pal 0x0a" : : -+ "r"(variant), "r"(pc), "r"(pa_pcb), "r"(newvptptr), "r"(newpv)); - __builtin_unreachable (); - } - - void --do_start(unsigned long memsize, void (*kernel_entry)(void), unsigned long cpus) -+do_start(unsigned long memsize, void (*kernel_entry)(void), -+ unsigned long config) - { - last_alloc = _end; - - init_page_table(); -- init_hwrpb(memsize, cpus); - init_pcb(); - init_i8259(); - uart_init(); - ps2port_setup(); - pci_setup(); - vgahw_init(); -+ init_hwrpb(memsize, config); - -- swppal(kernel_entry ? kernel_entry : do_console, &pcb); -+ void *new_pc = kernel_entry ? kernel_entry : do_console; -+ -+ swppal(new_pc, &pcb, VPTPTR, (unsigned long)new_pc); - } - - void -@@ -315,14 +359,16 @@ do_start_wait(unsigned long cpuid) - { - /* ??? The only message I know of is "START\r\n". - I can't be bothered to verify more than 4 characters. */ -- /* ??? The Linux kernel fills in, but does not require, -- CPU_restart_data. It just sets that to the same address -- as CPU_restart itself. Our swppal *does* put the PC into -- $26 and $27, the latter of which the kernel does rely upon. */ -+ -+ /* Use use a private extension to SWPPAL to get the -+ CPU_restart_data into $27. Linux fills it in, but does -+ not require it. Other operating system, however,s do use -+ CPU_restart_data as part of secondary CPU start-up. */ - - unsigned int len = hwrpb.processor[cpuid].ipc_buffer[0]; - unsigned int msg = hwrpb.processor[cpuid].ipc_buffer[1]; - void *CPU_restart = hwrpb.hwrpb.CPU_restart; -+ unsigned long CPU_restart_data = hwrpb.hwrpb.CPU_restart_data; - __sync_synchronize(); - hwrpb.hwrpb.rxrdy = 0; - -@@ -330,7 +376,8 @@ do_start_wait(unsigned long cpuid) - { - /* Set bootstrap in progress */ - hwrpb.processor[cpuid].flags |= 1; -- swppal(CPU_restart, hwrpb.processor[cpuid].hwpcb); -+ swppal(CPU_restart, hwrpb.processor[cpuid].hwpcb, -+ hwrpb.hwrpb.vptb, CPU_restart_data); - } - } - } diff --git a/emulators/qemu/patches/patch-roms_qemu-palcode_memcpy.c b/emulators/qemu/patches/patch-roms_qemu-palcode_memcpy.c deleted file mode 100644 index f381ca52bc4..00000000000 --- a/emulators/qemu/patches/patch-roms_qemu-palcode_memcpy.c +++ /dev/null @@ -1,15 +0,0 @@ -$NetBSD: patch-roms_qemu-palcode_memcpy.c,v 1.1 2020/10/04 20:39:25 thorpej Exp $ - -Include local header file for prototypes. - ---- roms/qemu-palcode/memcpy.c.orig 2020-10-04 16:22:55.342263484 +0000 -+++ roms/qemu-palcode/memcpy.c 2020-10-04 16:23:41.685256308 +0000 -@@ -8,7 +8,7 @@ - * This is a reasonably optimized memcpy() routine. - */ - --#include <string.h> -+#include "protos.h" - - /* - * Note that the C code is written to be optimized into good assembly. However, diff --git a/emulators/qemu/patches/patch-roms_qemu-palcode_memset.c b/emulators/qemu/patches/patch-roms_qemu-palcode_memset.c deleted file mode 100644 index b7ed0b6054a..00000000000 --- a/emulators/qemu/patches/patch-roms_qemu-palcode_memset.c +++ /dev/null @@ -1,15 +0,0 @@ -$NetBSD: patch-roms_qemu-palcode_memset.c,v 1.1 2020/10/04 20:39:25 thorpej Exp $ - -Include local header file for prototypes. - ---- roms/qemu-palcode/memset.c.orig 2020-10-04 16:26:11.159949099 +0000 -+++ roms/qemu-palcode/memset.c 2020-10-04 16:29:02.795766148 +0000 -@@ -19,7 +19,7 @@ - <http://www.gnu.org/licenses/>. */ - - --#include <string.h> -+#include "protos.h" - - void *memset(void *optr, int ival, unsigned long size) - { diff --git a/emulators/qemu/patches/patch-roms_qemu-palcode_pal.S b/emulators/qemu/patches/patch-roms_qemu-palcode_pal.S deleted file mode 100644 index 4299772250f..00000000000 --- a/emulators/qemu/patches/patch-roms_qemu-palcode_pal.S +++ /dev/null @@ -1,65 +0,0 @@ -$NetBSD: patch-roms_qemu-palcode_pal.S,v 1.2 2021/05/23 13:53:10 thorpej Exp $ - -In the unaligned access exception vector, fix an apparent typo that -prevented the return PC from being stored in the trap frame. - -In SWPPAL, allow an additional, non-architected argument for the -switch to OSF/1 PALcode. This extra argument specifies the desired -value of $pv after SWPPAL has completed, and is for internal PALcode -use only and is needed for secondary CPU spin-up. This is allowed -because per the architecure specification, all registers other than -$sp and $v0 are UNPREDICTABLE after SWPPAL, and this PALcode's use -of SWPPAL for secondary CPU spin-up is an implementation detail. -This PALcode was already relying on this UNPREDICTABLE behavior for -its own purposes; this change merely gives control of this behavior -to internal SWPPAL callers. - ---- roms/qemu-palcode/pal.S.orig 2020-12-08 17:00:57.000000000 +0000 -+++ roms/qemu-palcode/pal.S 2021-05-23 06:23:53.826566568 +0000 -@@ -278,7 +278,7 @@ Pal_Unalign: - blbs p6, MchkBugCheck - addq p6, 4, p6 // increment past the faulting insn - -- STACK_FRAME p0, p1, p2, 1 -+ STACK_FRAME p0, p6, p2, 1 - - mfpr p0, ptEntUna - mfpr $gp, ptKgp -@@ -566,6 +566,8 @@ ENDFN CallPal_Cserve_Cont - * r17 (a1) = New PC - * r18 (a2) = New PCB - * r19 (a3) = New VptPtr -+ * r20 (a4) = New Procedure Value (to place into $27) -+ * (Non-standard; See note below.) - * - * OUTPUT PARAMETERS: - * -@@ -574,11 +576,15 @@ ENDFN CallPal_Cserve_Cont - * 1 - Unknown PALcode variant - * 2 - Known PALcode variant, but PALcode not loaded - * -- * r26 (ra) = r27 (pv) = New PC -- * Note that this is non-architected, but is relied on by -+ * r26 (ra) = New PC -+ * r27 (pv) = From $20 -+ * Note that this is non-architected, but is relied upon by - * the usage of SwpPal within our own console code in order -- * to simplify its use within C code. -- * -+ * to simplify its use within C code. We can get away with -+ * the extra non-standard argument (in $20) because as -+ * architected, all registers except SP and R0 are -+ * UNPREDICTABLE; therefore private internal usage is -+ * fine. - */ - ORG_CALL_PAL_PRIV(0x0A) - CallPal_SwpPal: -@@ -624,7 +630,7 @@ CallPal_SwpPal_Cont: - mtpr $31, qemu_tbia // Flush TLB for new PTBR - - mov a1, $26 -- mov a1, $27 -+ mov a4, $27 - hw_ret (a1) - ENDFN CallPal_SwpPal_Cont - .previous diff --git a/emulators/qemu/patches/patch-roms_qemu-palcode_pci.c b/emulators/qemu/patches/patch-roms_qemu-palcode_pci.c deleted file mode 100644 index 651cb2db953..00000000000 --- a/emulators/qemu/patches/patch-roms_qemu-palcode_pci.c +++ /dev/null @@ -1,78 +0,0 @@ -$NetBSD: patch-roms_qemu-palcode_pci.c,v 1.1 2020/10/04 20:39:25 thorpej Exp $ - -- Move PCI_DEVFN(), PCI_BUS(), PCI_SLOT(), and PCI_FUNC() to pci.h. -- Improve debug/info messages. -- Only program a BAR as a 64-bit MEM BAR if it really is a 64-bit MEM BAR. - Fixes an issue with the CMD646 IDE controller under NetBSD. -- Use system-specific information to program the interrupt line register - with the interrupt mappings, which is what the SRM console does on real - hardware; some operating systems (e.g. NetBSD) use this information - rather than having interrupt mapping tables for every possible system - variation. - ---- roms/qemu-palcode/pci.c.orig 2020-10-04 16:41:22.923562768 +0000 -+++ roms/qemu-palcode/pci.c 2020-10-04 16:41:58.183954279 +0000 -@@ -29,12 +29,9 @@ - #include "protos.h" - #include "pci.h" - #include "pci_regs.h" -+#include SYSTEM_H - - --#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) --#define PCI_BUS(devfn) ((devfn) >> 8) --#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) --#define PCI_FUNC(devfn) ((devfn) & 0x07) - #define PCI_SLOT_MAX 32 - #define PCI_FUNC_MAX 8 - #define PCI_REGION_ROM 6 -@@ -88,7 +85,7 @@ pci_setup_device(int bdf, uint32_t *p_io - device_id = pci_config_readw(bdf, PCI_DEVICE_ID); - class_id = pci_config_readw(bdf, PCI_CLASS_DEVICE); - -- printf("PCI: %02x:%02x:%x class %04x id %04x:%04x\r\n", -+ printf("PCI: %d:%d:%d class %04x id %04x:%04x\r\n", - PCI_BUS(bdf), PCI_SLOT(bdf), PCI_FUNC(bdf), - class_id, vendor_id, device_id); - -@@ -122,9 +119,11 @@ pci_setup_device(int bdf, uint32_t *p_io - *p_base = addr + size; - pci_config_writel(bdf, ofs, addr); - -- printf("PCI: region %d: %08x\r\n", region, addr); -+ printf("PCI: region %d (BAR %02x): %08x\r\n", -+ region, ofs, addr); - -- if ((val & PCI_BASE_ADDRESS_MEM_TYPE_MASK) -+ if ((old & PCI_BASE_ADDRESS_SPACE_IO) == 0 && -+ (old & PCI_BASE_ADDRESS_MEM_TYPE_MASK) - == PCI_BASE_ADDRESS_MEM_TYPE_64) - { - pci_config_writel(bdf, ofs + 4, 0); -@@ -135,7 +134,25 @@ pci_setup_device(int bdf, uint32_t *p_io - - pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_IO | PCI_COMMAND_MEMORY); - -- /* Map the interrupt. */ -+ /* Map the interrupt and program the IRQ into the line register. -+ Some operating systems rely on the Console providing this information -+ in order to avoid having mapping tables for every possible system -+ variation. */ -+ -+ const uint8_t pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN); -+ const uint8_t slot = PCI_SLOT(bdf); -+ const int irq = MAP_PCI_INTERRUPT(slot, pin, class_id); -+ -+ if (irq == -1) -+ { -+ /* No interrupt mapping. */ -+ pci_config_writeb(bdf, PCI_INTERRUPT_LINE, 0xff); -+ } -+ else -+ { -+ printf("PCI: intr pin %d -> irq %d\r\n", pin, irq); -+ pci_config_writeb(bdf, PCI_INTERRUPT_LINE, irq); -+ } - } - - void diff --git a/emulators/qemu/patches/patch-roms_qemu-palcode_pci.h b/emulators/qemu/patches/patch-roms_qemu-palcode_pci.h deleted file mode 100644 index a3510126bf0..00000000000 --- a/emulators/qemu/patches/patch-roms_qemu-palcode_pci.h +++ /dev/null @@ -1,18 +0,0 @@ -$NetBSD: patch-roms_qemu-palcode_pci.h,v 1.1 2020/10/04 20:39:25 thorpej Exp $ - -Move PCI_DEVFN(), PCI_BUS(), PCI_SLOT(), and PCI_FUNC() to pci.h. - ---- roms/qemu-palcode/pci.h.orig 2020-10-04 16:48:50.267686138 +0000 -+++ roms/qemu-palcode/pci.h 2020-10-04 16:49:11.064722703 +0000 -@@ -60,6 +60,11 @@ extern void pci_config_maskw(int bdf, in - - extern int pci_next(int bdf, int *pmax); - -+#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) -+#define PCI_BUS(devfn) ((devfn) >> 8) -+#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) -+#define PCI_FUNC(devfn) ((devfn) & 0x07) -+ - #define foreachpci(BDF, MAX) \ - for (MAX = 0x0100, BDF = pci_next(0, &MAX); \ - BDF >= 0; \ diff --git a/emulators/qemu/patches/patch-roms_qemu-palcode_printf.c b/emulators/qemu/patches/patch-roms_qemu-palcode_printf.c deleted file mode 100644 index f0a08c73c51..00000000000 --- a/emulators/qemu/patches/patch-roms_qemu-palcode_printf.c +++ /dev/null @@ -1,31 +0,0 @@ -$NetBSD: patch-roms_qemu-palcode_printf.c,v 1.1 2020/10/04 20:39:25 thorpej Exp $ - -- Include local header file for prototypes. -- Add puts(), which the compiler may emit a call to if the string passed - to printf has no format specifiers. - ---- roms/qemu-palcode/printf.c.orig 2020-10-04 17:01:51.396706889 +0000 -+++ roms/qemu-palcode/printf.c 2020-10-04 17:02:27.588036847 +0000 -@@ -18,10 +18,8 @@ - along with this program; see the file COPYING. If not see - <http://www.gnu.org/licenses/>. */ - --#include <stdarg.h> --#include <stdbool.h> --#include <string.h> - #include "console.h" -+#include "protos.h" - - static int print_buf_pad(char *buf, int buflen, char *p, int width, int pad) - { -@@ -201,3 +199,10 @@ int printf(const char *fmt, ...) - va_end(args); - return r; - } -+ -+int puts(const char *s) -+{ -+ int len = strlen(s); -+ crb_puts(0, s, len); -+ return len; -+} diff --git a/emulators/qemu/patches/patch-roms_qemu-palcode_protos.h b/emulators/qemu/patches/patch-roms_qemu-palcode_protos.h deleted file mode 100644 index cb16ba3fce4..00000000000 --- a/emulators/qemu/patches/patch-roms_qemu-palcode_protos.h +++ /dev/null @@ -1,66 +0,0 @@ -$NetBSD: patch-roms_qemu-palcode_protos.h,v 1.1 2020/10/04 20:39:25 thorpej Exp $ - -- Don't include system headers. Instead, provide standalone definitions - and declarations of types needed and functions used by the PALcode that - are compatible with the standard Alpha / GCC ABI. -- Add pci_vga_bus and pci_vga_dev globals so that the HWRPB CTB can - correctly reflect the location of the a graphics console. - ---- roms/qemu-palcode/protos.h.orig 2020-10-04 17:05:39.239008051 +0000 -+++ roms/qemu-palcode/protos.h 2020-10-04 17:06:01.772319919 +0000 -@@ -21,11 +21,33 @@ - #ifndef PROTOS_H - #define PROTOS_H 1 - --#include <stdint.h> --#include <stdbool.h> --#include <stddef.h> --#include <string.h> -- -+/* -+ * Stand-alone definitions for various types, compatible with -+ * the Alpha Linux ABI and GCC. This eliminates dependencies -+ * on external headers. -+ */ -+typedef unsigned char uint8_t; -+typedef unsigned short uint16_t; -+typedef unsigned int uint32_t; -+typedef unsigned long uint64_t; -+typedef unsigned long size_t; -+ -+#define bool _Bool -+#define true 1 -+#define false 0 -+ -+#define offsetof(type, member) __builtin_offsetof(type, member) -+ -+typedef __builtin_va_list va_list; -+#define va_start(ap, last) __builtin_va_start((ap), (last)) -+#define va_arg __builtin_va_arg -+#define va_end(ap) __builtin_va_end(ap) -+ -+#define NULL ((void *)0) -+ -+extern void *memset(void *, int, size_t); -+extern void *memcpy(void *, const void *, size_t); -+extern size_t strlen(const char *); - - /* - * Call_Pal functions. -@@ -202,6 +224,8 @@ extern unsigned long crb_fixup(unsigned - */ - - extern bool have_vga; -+extern unsigned int pci_vga_bus; -+extern unsigned int pci_vga_dev; - - extern void do_console(void); - extern void entInt(void); -@@ -211,6 +235,7 @@ extern void entInt(void); - */ - - extern int printf(const char *, ...); -+extern int puts(const char *); - extern void ndelay(unsigned long nsec); - - static inline void udelay(unsigned long msec) diff --git a/emulators/qemu/patches/patch-roms_qemu-palcode_sys-clipper.h b/emulators/qemu/patches/patch-roms_qemu-palcode_sys-clipper.h deleted file mode 100644 index c16ad0c3ee0..00000000000 --- a/emulators/qemu/patches/patch-roms_qemu-palcode_sys-clipper.h +++ /dev/null @@ -1,38 +0,0 @@ -$NetBSD: patch-roms_qemu-palcode_sys-clipper.h,v 1.1 2020/10/04 20:39:25 thorpej Exp $ - -Povide PCI device interrupt mapping information. - ---- roms/qemu-palcode/sys-clipper.h.orig 2020-10-04 17:10:06.597880613 +0000 -+++ roms/qemu-palcode/sys-clipper.h 2020-10-04 17:10:33.149119398 +0000 -@@ -27,4 +27,31 @@ - #define SYS_VARIATION (5 << 10) - #define SYS_REVISION 0 - -+#ifndef __ASSEMBLER__ -+ -+#define MAP_PCI_INTERRUPT(SLOT, PIN, CLASS_ID) \ -+({ \ -+ int IRQ; \ -+ \ -+ if (CLASS_ID == 0x0601) \ -+ { \ -+ /* PCI-ISA bridge is hard-wired to IRQ 55 on real hardware, \ -+ and comes in at a different SCB vector; force the line \ -+ register to -1. */ \ -+ IRQ = -1; \ -+ } \ -+ else if (PIN >= 1 && PIN <= 4) \ -+ { \ -+ /* See hw/alpha/dp264.c:clipper_pci_map_irq() */ \ -+ IRQ = (SLOT + 1) * 4 + (PIN - 1); \ -+ } \ -+ else \ -+ { \ -+ IRQ = -1; \ -+ } \ -+ IRQ; \ -+}) -+ -+#endif /* ! __ASSEMBLER__ */ -+ - #endif diff --git a/emulators/qemu/patches/patch-roms_qemu-palcode_vgaio.c b/emulators/qemu/patches/patch-roms_qemu-palcode_vgaio.c deleted file mode 100644 index 066d212d846..00000000000 --- a/emulators/qemu/patches/patch-roms_qemu-palcode_vgaio.c +++ /dev/null @@ -1,16 +0,0 @@ -$NetBSD: patch-roms_qemu-palcode_vgaio.c,v 1.1 2020/10/04 20:39:25 thorpej Exp $ - -Add pci_vga_bus and pci_vga_dev globals so that the HWRPB CTB can -correctly reflect the location of the a graphics console. - ---- roms/qemu-palcode/vgaio.c.orig 2020-10-04 17:12:53.089367837 +0000 -+++ roms/qemu-palcode/vgaio.c 2020-10-04 17:13:21.240322169 +0000 -@@ -570,6 +570,8 @@ vgahw_init(void) - - found: - have_vga = 1; -+ pci_vga_bus = PCI_BUS(bdf); -+ pci_vga_dev = PCI_SLOT(bdf); - - vmode_g = find_vga_entry(3); - diff --git a/emulators/qemu/patches/patch-roms_u-boot_tools_imx8m__image.sh b/emulators/qemu/patches/patch-roms_u-boot_tools_imx8m__image.sh deleted file mode 100644 index 177dfaf2e84..00000000000 --- a/emulators/qemu/patches/patch-roms_u-boot_tools_imx8m__image.sh +++ /dev/null @@ -1,24 +0,0 @@ -$NetBSD: patch-roms_u-boot_tools_imx8m__image.sh,v 1.1 2019/04/24 13:59:32 ryoon Exp $ - -* Improve POSIX shell portability - ---- roms/u-boot/tools/imx8m_image.sh.orig 2019-04-23 18:16:46.000000000 +0000 -+++ roms/u-boot/tools/imx8m_image.sh -@@ -12,7 +12,7 @@ blobs=`awk '/^SIGNED_HDMI/ {print $2} /^ - for f in $blobs; do - tmp=$srctree/$f - -- if [ $f == "spl/u-boot-spl-ddr.bin" ] || [ $f == "u-boot.itb" ]; then -+ if [ $f = "spl/u-boot-spl-ddr.bin" ] || [ $f = "u-boot.itb" ]; then - continue - fi - -@@ -28,7 +28,7 @@ for f in $blobs; do - sed -in "s;$f;$tmp;" $file - done - --if [ $post_process == 1 ]; then -+if [ $post_process = 1 ]; then - if [ -f $srctree/lpddr4_pmu_train_1d_imem.bin ]; then - objcopy -I binary -O binary --pad-to 0x8000 --gap-fill=0x0 $srctree/lpddr4_pmu_train_1d_imem.bin lpddr4_pmu_train_1d_imem_pad.bin - objcopy -I binary -O binary --pad-to 0x4000 --gap-fill=0x0 $srctree/lpddr4_pmu_train_1d_dmem.bin lpddr4_pmu_train_1d_dmem_pad.bin diff --git a/emulators/qemu/patches/patch-target_alpha_translate.c b/emulators/qemu/patches/patch-target_alpha_translate.c deleted file mode 100644 index a5bbd444ac1..00000000000 --- a/emulators/qemu/patches/patch-target_alpha_translate.c +++ /dev/null @@ -1,421 +0,0 @@ -$NetBSD: patch-target_alpha_translate.c,v 1.1 2021/06/22 04:09:06 thorpej Exp $ - -Patch from upstream (not integrated there yet) to require FEN to be -enabled for floating point operations, and to properly deliver FEN -traps if not. Fixes many users of floating point (jot(1), awk(1), etc.) -on NetBSD/alpha under Qemu. - - https://gitlab.com/qemu-project/qemu/-/issues/438 - ---- target/alpha/translate.c.orig 2021-04-29 17:18:59.000000000 +0000 -+++ target/alpha/translate.c 2021-06-22 00:26:30.693822791 +0000 -@@ -1471,6 +1471,13 @@ static DisasJumpType gen_mtpr(DisasConte - } \ - } while (0) - -+#define REQUIRE_FEN \ -+ do { \ -+ if (!(ctx->tbflags & ENV_FLAG_FEN)) { \ -+ goto raise_fen; \ -+ } \ -+ } while (0) -+ - static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) - { - int32_t disp21, disp16, disp12 __attribute__((unused)); -@@ -2066,6 +2073,7 @@ static DisasJumpType translate_one(Disas - case 0x04: - /* ITOFS */ - REQUIRE_REG_31(rb); -+ REQUIRE_FEN; - t32 = tcg_temp_new_i32(); - va = load_gpr(ctx, ra); - tcg_gen_extrl_i64_i32(t32, va); -@@ -2075,17 +2083,20 @@ static DisasJumpType translate_one(Disas - case 0x0A: - /* SQRTF */ - REQUIRE_REG_31(ra); -+ REQUIRE_FEN; - vb = load_fpr(ctx, rb); - gen_helper_sqrtf(vc, cpu_env, vb); - break; - case 0x0B: - /* SQRTS */ - REQUIRE_REG_31(ra); -+ REQUIRE_FEN; - gen_sqrts(ctx, rb, rc, fn11); - break; - case 0x14: - /* ITOFF */ - REQUIRE_REG_31(rb); -+ REQUIRE_FEN; - t32 = tcg_temp_new_i32(); - va = load_gpr(ctx, ra); - tcg_gen_extrl_i64_i32(t32, va); -@@ -2095,18 +2106,21 @@ static DisasJumpType translate_one(Disas - case 0x24: - /* ITOFT */ - REQUIRE_REG_31(rb); -+ REQUIRE_FEN; - va = load_gpr(ctx, ra); - tcg_gen_mov_i64(vc, va); - break; - case 0x2A: - /* SQRTG */ - REQUIRE_REG_31(ra); -+ REQUIRE_FEN; - vb = load_fpr(ctx, rb); - gen_helper_sqrtg(vc, cpu_env, vb); - break; - case 0x02B: - /* SQRTT */ - REQUIRE_REG_31(ra); -+ REQUIRE_FEN; - gen_sqrtt(ctx, rb, rc, fn11); - break; - default: -@@ -2123,18 +2137,22 @@ static DisasJumpType translate_one(Disas - switch (fpfn) { /* fn11 & 0x3F */ - case 0x00: - /* ADDF */ -+ REQUIRE_FEN; - gen_helper_addf(vc, cpu_env, va, vb); - break; - case 0x01: - /* SUBF */ -+ REQUIRE_FEN; - gen_helper_subf(vc, cpu_env, va, vb); - break; - case 0x02: - /* MULF */ -+ REQUIRE_FEN; - gen_helper_mulf(vc, cpu_env, va, vb); - break; - case 0x03: - /* DIVF */ -+ REQUIRE_FEN; - gen_helper_divf(vc, cpu_env, va, vb); - break; - case 0x1E: -@@ -2143,35 +2161,43 @@ static DisasJumpType translate_one(Disas - goto invalid_opc; - case 0x20: - /* ADDG */ -+ REQUIRE_FEN; - gen_helper_addg(vc, cpu_env, va, vb); - break; - case 0x21: - /* SUBG */ -+ REQUIRE_FEN; - gen_helper_subg(vc, cpu_env, va, vb); - break; - case 0x22: - /* MULG */ -+ REQUIRE_FEN; - gen_helper_mulg(vc, cpu_env, va, vb); - break; - case 0x23: - /* DIVG */ -+ REQUIRE_FEN; - gen_helper_divg(vc, cpu_env, va, vb); - break; - case 0x25: - /* CMPGEQ */ -+ REQUIRE_FEN; - gen_helper_cmpgeq(vc, cpu_env, va, vb); - break; - case 0x26: - /* CMPGLT */ -+ REQUIRE_FEN; - gen_helper_cmpglt(vc, cpu_env, va, vb); - break; - case 0x27: - /* CMPGLE */ -+ REQUIRE_FEN; - gen_helper_cmpgle(vc, cpu_env, va, vb); - break; - case 0x2C: - /* CVTGF */ - REQUIRE_REG_31(ra); -+ REQUIRE_FEN; - gen_helper_cvtgf(vc, cpu_env, vb); - break; - case 0x2D: -@@ -2181,16 +2207,19 @@ static DisasJumpType translate_one(Disas - case 0x2F: - /* CVTGQ */ - REQUIRE_REG_31(ra); -+ REQUIRE_FEN; - gen_helper_cvtgq(vc, cpu_env, vb); - break; - case 0x3C: - /* CVTQF */ - REQUIRE_REG_31(ra); -+ REQUIRE_FEN; - gen_helper_cvtqf(vc, cpu_env, vb); - break; - case 0x3E: - /* CVTQG */ - REQUIRE_REG_31(ra); -+ REQUIRE_FEN; - gen_helper_cvtqg(vc, cpu_env, vb); - break; - default: -@@ -2203,54 +2232,67 @@ static DisasJumpType translate_one(Disas - switch (fpfn) { /* fn11 & 0x3F */ - case 0x00: - /* ADDS */ -+ REQUIRE_FEN; - gen_adds(ctx, ra, rb, rc, fn11); - break; - case 0x01: - /* SUBS */ -+ REQUIRE_FEN; - gen_subs(ctx, ra, rb, rc, fn11); - break; - case 0x02: - /* MULS */ -+ REQUIRE_FEN; - gen_muls(ctx, ra, rb, rc, fn11); - break; - case 0x03: - /* DIVS */ -+ REQUIRE_FEN; - gen_divs(ctx, ra, rb, rc, fn11); - break; - case 0x20: - /* ADDT */ -+ REQUIRE_FEN; - gen_addt(ctx, ra, rb, rc, fn11); - break; - case 0x21: - /* SUBT */ -+ REQUIRE_FEN; - gen_subt(ctx, ra, rb, rc, fn11); - break; - case 0x22: - /* MULT */ -+ REQUIRE_FEN; - gen_mult(ctx, ra, rb, rc, fn11); - break; - case 0x23: - /* DIVT */ -+ REQUIRE_FEN; - gen_divt(ctx, ra, rb, rc, fn11); - break; - case 0x24: - /* CMPTUN */ -+ REQUIRE_FEN; - gen_cmptun(ctx, ra, rb, rc, fn11); - break; - case 0x25: - /* CMPTEQ */ -+ REQUIRE_FEN; - gen_cmpteq(ctx, ra, rb, rc, fn11); - break; - case 0x26: - /* CMPTLT */ -+ REQUIRE_FEN; - gen_cmptlt(ctx, ra, rb, rc, fn11); - break; - case 0x27: - /* CMPTLE */ -+ REQUIRE_FEN; - gen_cmptle(ctx, ra, rb, rc, fn11); - break; - case 0x2C: - REQUIRE_REG_31(ra); -+ REQUIRE_FEN; - if (fn11 == 0x2AC || fn11 == 0x6AC) { - /* CVTST */ - gen_cvtst(ctx, rb, rc, fn11); -@@ -2262,16 +2304,19 @@ static DisasJumpType translate_one(Disas - case 0x2F: - /* CVTTQ */ - REQUIRE_REG_31(ra); -+ REQUIRE_FEN; - gen_cvttq(ctx, rb, rc, fn11); - break; - case 0x3C: - /* CVTQS */ - REQUIRE_REG_31(ra); -+ REQUIRE_FEN; - gen_cvtqs(ctx, rb, rc, fn11); - break; - case 0x3E: - /* CVTQT */ - REQUIRE_REG_31(ra); -+ REQUIRE_FEN; - gen_cvtqt(ctx, rb, rc, fn11); - break; - default: -@@ -2284,12 +2329,14 @@ static DisasJumpType translate_one(Disas - case 0x010: - /* CVTLQ */ - REQUIRE_REG_31(ra); -+ REQUIRE_FEN; - vc = dest_fpr(ctx, rc); - vb = load_fpr(ctx, rb); - gen_cvtlq(vc, vb); - break; - case 0x020: - /* CPYS */ -+ REQUIRE_FEN; - if (rc == 31) { - /* Special case CPYS as FNOP. */ - } else { -@@ -2306,6 +2353,7 @@ static DisasJumpType translate_one(Disas - break; - case 0x021: - /* CPYSN */ -+ REQUIRE_FEN; - vc = dest_fpr(ctx, rc); - vb = load_fpr(ctx, rb); - va = load_fpr(ctx, ra); -@@ -2313,6 +2361,7 @@ static DisasJumpType translate_one(Disas - break; - case 0x022: - /* CPYSE */ -+ REQUIRE_FEN; - vc = dest_fpr(ctx, rc); - vb = load_fpr(ctx, rb); - va = load_fpr(ctx, ra); -@@ -2320,6 +2369,7 @@ static DisasJumpType translate_one(Disas - break; - case 0x024: - /* MT_FPCR */ -+ REQUIRE_FEN; - va = load_fpr(ctx, ra); - gen_helper_store_fpcr(cpu_env, va); - if (ctx->tb_rm == QUAL_RM_D) { -@@ -2330,37 +2380,45 @@ static DisasJumpType translate_one(Disas - break; - case 0x025: - /* MF_FPCR */ -+ REQUIRE_FEN; - va = dest_fpr(ctx, ra); - gen_helper_load_fpcr(va, cpu_env); - break; - case 0x02A: - /* FCMOVEQ */ -+ REQUIRE_FEN; - gen_fcmov(ctx, TCG_COND_EQ, ra, rb, rc); - break; - case 0x02B: - /* FCMOVNE */ -+ REQUIRE_FEN; - gen_fcmov(ctx, TCG_COND_NE, ra, rb, rc); - break; - case 0x02C: - /* FCMOVLT */ -+ REQUIRE_FEN; - gen_fcmov(ctx, TCG_COND_LT, ra, rb, rc); - break; - case 0x02D: - /* FCMOVGE */ -+ REQUIRE_FEN; - gen_fcmov(ctx, TCG_COND_GE, ra, rb, rc); - break; - case 0x02E: - /* FCMOVLE */ -+ REQUIRE_FEN; - gen_fcmov(ctx, TCG_COND_LE, ra, rb, rc); - break; - case 0x02F: - /* FCMOVGT */ -+ REQUIRE_FEN; - gen_fcmov(ctx, TCG_COND_GT, ra, rb, rc); - break; - case 0x030: /* CVTQL */ - case 0x130: /* CVTQL/V */ - case 0x530: /* CVTQL/SV */ - REQUIRE_REG_31(ra); -+ REQUIRE_FEN; - vc = dest_fpr(ctx, rc); - vb = load_fpr(ctx, rb); - gen_helper_cvtql(vc, cpu_env, vb); -@@ -2793,34 +2851,42 @@ static DisasJumpType translate_one(Disas - #endif - case 0x20: - /* LDF */ -+ REQUIRE_FEN; - gen_load_mem(ctx, &gen_qemu_ldf, ra, rb, disp16, 1, 0); - break; - case 0x21: - /* LDG */ -+ REQUIRE_FEN; - gen_load_mem(ctx, &gen_qemu_ldg, ra, rb, disp16, 1, 0); - break; - case 0x22: - /* LDS */ -+ REQUIRE_FEN; - gen_load_mem(ctx, &gen_qemu_lds, ra, rb, disp16, 1, 0); - break; - case 0x23: - /* LDT */ -+ REQUIRE_FEN; - gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 1, 0); - break; - case 0x24: - /* STF */ -+ REQUIRE_FEN; - gen_store_mem(ctx, &gen_qemu_stf, ra, rb, disp16, 1, 0); - break; - case 0x25: - /* STG */ -+ REQUIRE_FEN; - gen_store_mem(ctx, &gen_qemu_stg, ra, rb, disp16, 1, 0); - break; - case 0x26: - /* STS */ -+ REQUIRE_FEN; - gen_store_mem(ctx, &gen_qemu_sts, ra, rb, disp16, 1, 0); - break; - case 0x27: - /* STT */ -+ REQUIRE_FEN; - gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 1, 0); - break; - case 0x28: -@@ -2862,12 +2928,15 @@ static DisasJumpType translate_one(Disas - ret = gen_bdirect(ctx, ra, disp21); - break; - case 0x31: /* FBEQ */ -+ REQUIRE_FEN; - ret = gen_fbcond(ctx, TCG_COND_EQ, ra, disp21); - break; - case 0x32: /* FBLT */ -+ REQUIRE_FEN; - ret = gen_fbcond(ctx, TCG_COND_LT, ra, disp21); - break; - case 0x33: /* FBLE */ -+ REQUIRE_FEN; - ret = gen_fbcond(ctx, TCG_COND_LE, ra, disp21); - break; - case 0x34: -@@ -2875,12 +2944,15 @@ static DisasJumpType translate_one(Disas - ret = gen_bdirect(ctx, ra, disp21); - break; - case 0x35: /* FBNE */ -+ REQUIRE_FEN; - ret = gen_fbcond(ctx, TCG_COND_NE, ra, disp21); - break; - case 0x36: /* FBGE */ -+ REQUIRE_FEN; - ret = gen_fbcond(ctx, TCG_COND_GE, ra, disp21); - break; - case 0x37: /* FBGT */ -+ REQUIRE_FEN; - ret = gen_fbcond(ctx, TCG_COND_GT, ra, disp21); - break; - case 0x38: -@@ -2918,6 +2990,9 @@ static DisasJumpType translate_one(Disas - invalid_opc: - ret = gen_invalid(ctx); - break; -+ raise_fen: -+ ret = gen_excp(ctx, EXCP_FEN, 0); -+ break; - } - - return ret; diff --git a/emulators/qemu/patches/patch-target_i386_meson.build b/emulators/qemu/patches/patch-target_i386_meson.build deleted file mode 100644 index 3856bbf9233..00000000000 --- a/emulators/qemu/patches/patch-target_i386_meson.build +++ /dev/null @@ -1,12 +0,0 @@ -$NetBSD: patch-target_i386_meson.build,v 1.2 2021/05/24 14:22:08 ryoon Exp $ - ---- target/i386/meson.build.orig 2021-04-29 17:18:58.000000000 +0000 -+++ target/i386/meson.build -@@ -19,6 +19,7 @@ i386_softmmu_ss.add(files( - subdir('kvm') - subdir('hax') - subdir('whpx') -+subdir('nvmm') - subdir('hvf') - subdir('tcg') - diff --git a/emulators/qemu/patches/patch-target_i386_nvmm_meson.build b/emulators/qemu/patches/patch-target_i386_nvmm_meson.build deleted file mode 100644 index 1c5b2cd5062..00000000000 --- a/emulators/qemu/patches/patch-target_i386_nvmm_meson.build +++ /dev/null @@ -1,13 +0,0 @@ -$NetBSD: patch-target_i386_nvmm_meson.build,v 1.1 2021/05/24 14:22:08 ryoon Exp $ - ---- target/i386/nvmm/meson.build.orig 2021-05-06 05:09:24.910385600 +0000 -+++ target/i386/nvmm/meson.build -@@ -0,0 +1,8 @@ -+i386_softmmu_ss.add(when: 'CONFIG_NVMM', if_true: -+ files( -+ 'nvmm-all.c', -+ 'nvmm-accel-ops.c', -+ ) -+) -+ -+i386_softmmu_ss.add(when: 'CONFIG_NVMM', if_true: nvmm) diff --git a/emulators/qemu/patches/patch-target_i386_nvmm_nvmm-accel-ops.c b/emulators/qemu/patches/patch-target_i386_nvmm_nvmm-accel-ops.c deleted file mode 100644 index 9b91834f95f..00000000000 --- a/emulators/qemu/patches/patch-target_i386_nvmm_nvmm-accel-ops.c +++ /dev/null @@ -1,116 +0,0 @@ -$NetBSD: patch-target_i386_nvmm_nvmm-accel-ops.c,v 1.1 2021/05/24 14:22:08 ryoon Exp $ - ---- target/i386/nvmm/nvmm-accel-ops.c.orig 2021-05-06 05:09:24.910489458 +0000 -+++ target/i386/nvmm/nvmm-accel-ops.c -@@ -0,0 +1,111 @@ -+/* -+ * Copyright (c) 2018-2019 Maxime Villard, All rights reserved. -+ * -+ * NetBSD Virtual Machine Monitor (NVMM) accelerator for QEMU. -+ * -+ * This work is licensed under the terms of the GNU GPL, version 2 or later. -+ * See the COPYING file in the top-level directory. -+ */ -+ -+#include "qemu/osdep.h" -+#include "sysemu/kvm_int.h" -+#include "qemu/main-loop.h" -+#include "sysemu/cpus.h" -+#include "qemu/guest-random.h" -+ -+#include "sysemu/nvmm.h" -+#include "nvmm-accel-ops.h" -+ -+static void *qemu_nvmm_cpu_thread_fn(void *arg) -+{ -+ CPUState *cpu = arg; -+ int r; -+ -+ assert(nvmm_enabled()); -+ -+ rcu_register_thread(); -+ -+ qemu_mutex_lock_iothread(); -+ qemu_thread_get_self(cpu->thread); -+ cpu->thread_id = qemu_get_thread_id(); -+ current_cpu = cpu; -+ -+ r = nvmm_init_vcpu(cpu); -+ if (r < 0) { -+ fprintf(stderr, "nvmm_init_vcpu failed: %s\n", strerror(-r)); -+ exit(1); -+ } -+ -+ /* signal CPU creation */ -+ cpu_thread_signal_created(cpu); -+ qemu_guest_random_seed_thread_part2(cpu->random_seed); -+ -+ do { -+ if (cpu_can_run(cpu)) { -+ r = nvmm_vcpu_exec(cpu); -+ if (r == EXCP_DEBUG) { -+ cpu_handle_guest_debug(cpu); -+ } -+ } -+ while (cpu_thread_is_idle(cpu)) { -+ qemu_cond_wait_iothread(cpu->halt_cond); -+ } -+ qemu_wait_io_event_common(cpu); -+ } while (!cpu->unplug || cpu_can_run(cpu)); -+ -+ nvmm_destroy_vcpu(cpu); -+ cpu_thread_signal_destroyed(cpu); -+ qemu_mutex_unlock_iothread(); -+ rcu_unregister_thread(); -+ return NULL; -+} -+ -+static void nvmm_start_vcpu_thread(CPUState *cpu) -+{ -+ char thread_name[VCPU_THREAD_NAME_SIZE]; -+ -+ cpu->thread = g_malloc0(sizeof(QemuThread)); -+ cpu->halt_cond = g_malloc0(sizeof(QemuCond)); -+ qemu_cond_init(cpu->halt_cond); -+ snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/NVMM", -+ cpu->cpu_index); -+ qemu_thread_create(cpu->thread, thread_name, qemu_nvmm_cpu_thread_fn, -+ cpu, QEMU_THREAD_JOINABLE); -+} -+ -+/* -+ * Abort the call to run the virtual processor by another thread, and to -+ * return the control to that thread. -+ */ -+static void nvmm_kick_vcpu_thread(CPUState *cpu) -+{ -+ cpu->exit_request = 1; -+ cpus_kick_thread(cpu); -+} -+ -+static void nvmm_accel_ops_class_init(ObjectClass *oc, void *data) -+{ -+ AccelOpsClass *ops = ACCEL_OPS_CLASS(oc); -+ -+ ops->create_vcpu_thread = nvmm_start_vcpu_thread; -+ ops->kick_vcpu_thread = nvmm_kick_vcpu_thread; -+ -+ ops->synchronize_post_reset = nvmm_cpu_synchronize_post_reset; -+ ops->synchronize_post_init = nvmm_cpu_synchronize_post_init; -+ ops->synchronize_state = nvmm_cpu_synchronize_state; -+ ops->synchronize_pre_loadvm = nvmm_cpu_synchronize_pre_loadvm; -+} -+ -+static const TypeInfo nvmm_accel_ops_type = { -+ .name = ACCEL_OPS_NAME("nvmm"), -+ -+ .parent = TYPE_ACCEL_OPS, -+ .class_init = nvmm_accel_ops_class_init, -+ .abstract = true, -+}; -+ -+static void nvmm_accel_ops_register_types(void) -+{ -+ type_register_static(&nvmm_accel_ops_type); -+} -+type_init(nvmm_accel_ops_register_types); diff --git a/emulators/qemu/patches/patch-target_i386_nvmm_nvmm-accel-ops.h b/emulators/qemu/patches/patch-target_i386_nvmm_nvmm-accel-ops.h deleted file mode 100644 index 651525c9d25..00000000000 --- a/emulators/qemu/patches/patch-target_i386_nvmm_nvmm-accel-ops.h +++ /dev/null @@ -1,29 +0,0 @@ -$NetBSD: patch-target_i386_nvmm_nvmm-accel-ops.h,v 1.1 2021/05/24 14:22:08 ryoon Exp $ - ---- target/i386/nvmm/nvmm-accel-ops.h.orig 2021-05-06 05:09:24.910599351 +0000 -+++ target/i386/nvmm/nvmm-accel-ops.h -@@ -0,0 +1,24 @@ -+/* -+ * Copyright (c) 2018-2019 Maxime Villard, All rights reserved. -+ * -+ * NetBSD Virtual Machine Monitor (NVMM) accelerator for QEMU. -+ * -+ * This work is licensed under the terms of the GNU GPL, version 2 or later. -+ * See the COPYING file in the top-level directory. -+ */ -+ -+#ifndef NVMM_CPUS_H -+#define NVMM_CPUS_H -+ -+#include "sysemu/cpus.h" -+ -+int nvmm_init_vcpu(CPUState *cpu); -+int nvmm_vcpu_exec(CPUState *cpu); -+void nvmm_destroy_vcpu(CPUState *cpu); -+ -+void nvmm_cpu_synchronize_state(CPUState *cpu); -+void nvmm_cpu_synchronize_post_reset(CPUState *cpu); -+void nvmm_cpu_synchronize_post_init(CPUState *cpu); -+void nvmm_cpu_synchronize_pre_loadvm(CPUState *cpu); -+ -+#endif /* NVMM_CPUS_H */ diff --git a/emulators/qemu/patches/patch-target_i386_nvmm_nvmm-all.c b/emulators/qemu/patches/patch-target_i386_nvmm_nvmm-all.c deleted file mode 100644 index a0777907542..00000000000 --- a/emulators/qemu/patches/patch-target_i386_nvmm_nvmm-all.c +++ /dev/null @@ -1,1241 +0,0 @@ -$NetBSD: patch-target_i386_nvmm_nvmm-all.c,v 1.2 2021/06/01 16:28:05 nia Exp $ - ---- target/i386/nvmm/nvmm-all.c.orig 2021-06-01 15:07:31.572325819 +0000 -+++ target/i386/nvmm/nvmm-all.c -@@ -0,0 +1,1236 @@ -+/* -+ * Copyright (c) 2018-2019 Maxime Villard, All rights reserved. -+ * -+ * NetBSD Virtual Machine Monitor (NVMM) accelerator for QEMU. -+ * -+ * This work is licensed under the terms of the GNU GPL, version 2 or later. -+ * See the COPYING file in the top-level directory. -+ */ -+ -+#include "qemu/osdep.h" -+#include "cpu.h" -+#include "exec/address-spaces.h" -+#include "exec/ioport.h" -+#include "qemu-common.h" -+#include "qemu/accel.h" -+#include "sysemu/nvmm.h" -+#include "sysemu/cpus.h" -+#include "sysemu/runstate.h" -+#include "qemu/main-loop.h" -+#include "qemu/error-report.h" -+#include "qapi/error.h" -+#include "qemu/queue.h" -+#include "migration/blocker.h" -+#include "strings.h" -+ -+#include "nvmm-accel-ops.h" -+ -+#include <nvmm.h> -+ -+struct qemu_vcpu { -+ struct nvmm_vcpu vcpu; -+ uint8_t tpr; -+ bool stop; -+ -+ /* Window-exiting for INTs/NMIs. */ -+ bool int_window_exit; -+ bool nmi_window_exit; -+ -+ /* The guest is in an interrupt shadow (POP SS, etc). */ -+ bool int_shadow; -+}; -+ -+struct qemu_machine { -+ struct nvmm_capability cap; -+ struct nvmm_machine mach; -+}; -+ -+/* -------------------------------------------------------------------------- */ -+ -+static bool nvmm_allowed; -+static struct qemu_machine qemu_mach; -+ -+static struct qemu_vcpu * -+get_qemu_vcpu(CPUState *cpu) -+{ -+ return (struct qemu_vcpu *)cpu->hax_vcpu; -+} -+ -+static struct nvmm_machine * -+get_nvmm_mach(void) -+{ -+ return &qemu_mach.mach; -+} -+ -+/* -------------------------------------------------------------------------- */ -+ -+static void -+nvmm_set_segment(struct nvmm_x64_state_seg *nseg, const SegmentCache *qseg) -+{ -+ uint32_t attrib = qseg->flags; -+ -+ nseg->selector = qseg->selector; -+ nseg->limit = qseg->limit; -+ nseg->base = qseg->base; -+ nseg->attrib.type = __SHIFTOUT(attrib, DESC_TYPE_MASK); -+ nseg->attrib.s = __SHIFTOUT(attrib, DESC_S_MASK); -+ nseg->attrib.dpl = __SHIFTOUT(attrib, DESC_DPL_MASK); -+ nseg->attrib.p = __SHIFTOUT(attrib, DESC_P_MASK); -+ nseg->attrib.avl = __SHIFTOUT(attrib, DESC_AVL_MASK); -+ nseg->attrib.l = __SHIFTOUT(attrib, DESC_L_MASK); -+ nseg->attrib.def = __SHIFTOUT(attrib, DESC_B_MASK); -+ nseg->attrib.g = __SHIFTOUT(attrib, DESC_G_MASK); -+} -+ -+static void -+nvmm_set_registers(CPUState *cpu) -+{ -+ struct CPUX86State *env = (CPUArchState *)cpu->env_ptr; -+ struct nvmm_machine *mach = get_nvmm_mach(); -+ struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu); -+ struct nvmm_vcpu *vcpu = &qcpu->vcpu; -+ struct nvmm_x64_state *state = vcpu->state; -+ uint64_t bitmap; -+ size_t i; -+ int ret; -+ -+ assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); -+ -+ /* GPRs. */ -+ state->gprs[NVMM_X64_GPR_RAX] = env->regs[R_EAX]; -+ state->gprs[NVMM_X64_GPR_RCX] = env->regs[R_ECX]; -+ state->gprs[NVMM_X64_GPR_RDX] = env->regs[R_EDX]; -+ state->gprs[NVMM_X64_GPR_RBX] = env->regs[R_EBX]; -+ state->gprs[NVMM_X64_GPR_RSP] = env->regs[R_ESP]; -+ state->gprs[NVMM_X64_GPR_RBP] = env->regs[R_EBP]; -+ state->gprs[NVMM_X64_GPR_RSI] = env->regs[R_ESI]; -+ state->gprs[NVMM_X64_GPR_RDI] = env->regs[R_EDI]; -+#ifdef TARGET_X86_64 -+ state->gprs[NVMM_X64_GPR_R8] = env->regs[R_R8]; -+ state->gprs[NVMM_X64_GPR_R9] = env->regs[R_R9]; -+ state->gprs[NVMM_X64_GPR_R10] = env->regs[R_R10]; -+ state->gprs[NVMM_X64_GPR_R11] = env->regs[R_R11]; -+ state->gprs[NVMM_X64_GPR_R12] = env->regs[R_R12]; -+ state->gprs[NVMM_X64_GPR_R13] = env->regs[R_R13]; -+ state->gprs[NVMM_X64_GPR_R14] = env->regs[R_R14]; -+ state->gprs[NVMM_X64_GPR_R15] = env->regs[R_R15]; -+#endif -+ -+ /* RIP and RFLAGS. */ -+ state->gprs[NVMM_X64_GPR_RIP] = env->eip; -+ state->gprs[NVMM_X64_GPR_RFLAGS] = env->eflags; -+ -+ /* Segments. */ -+ nvmm_set_segment(&state->segs[NVMM_X64_SEG_CS], &env->segs[R_CS]); -+ nvmm_set_segment(&state->segs[NVMM_X64_SEG_DS], &env->segs[R_DS]); -+ nvmm_set_segment(&state->segs[NVMM_X64_SEG_ES], &env->segs[R_ES]); -+ nvmm_set_segment(&state->segs[NVMM_X64_SEG_FS], &env->segs[R_FS]); -+ nvmm_set_segment(&state->segs[NVMM_X64_SEG_GS], &env->segs[R_GS]); -+ nvmm_set_segment(&state->segs[NVMM_X64_SEG_SS], &env->segs[R_SS]); -+ -+ /* Special segments. */ -+ nvmm_set_segment(&state->segs[NVMM_X64_SEG_GDT], &env->gdt); -+ nvmm_set_segment(&state->segs[NVMM_X64_SEG_LDT], &env->ldt); -+ nvmm_set_segment(&state->segs[NVMM_X64_SEG_TR], &env->tr); -+ nvmm_set_segment(&state->segs[NVMM_X64_SEG_IDT], &env->idt); -+ -+ /* Control registers. */ -+ state->crs[NVMM_X64_CR_CR0] = env->cr[0]; -+ state->crs[NVMM_X64_CR_CR2] = env->cr[2]; -+ state->crs[NVMM_X64_CR_CR3] = env->cr[3]; -+ state->crs[NVMM_X64_CR_CR4] = env->cr[4]; -+ state->crs[NVMM_X64_CR_CR8] = qcpu->tpr; -+ state->crs[NVMM_X64_CR_XCR0] = env->xcr0; -+ -+ /* Debug registers. */ -+ state->drs[NVMM_X64_DR_DR0] = env->dr[0]; -+ state->drs[NVMM_X64_DR_DR1] = env->dr[1]; -+ state->drs[NVMM_X64_DR_DR2] = env->dr[2]; -+ state->drs[NVMM_X64_DR_DR3] = env->dr[3]; -+ state->drs[NVMM_X64_DR_DR6] = env->dr[6]; -+ state->drs[NVMM_X64_DR_DR7] = env->dr[7]; -+ -+ /* FPU. */ -+ state->fpu.fx_cw = env->fpuc; -+ state->fpu.fx_sw = (env->fpus & ~0x3800) | ((env->fpstt & 0x7) << 11); -+ state->fpu.fx_tw = 0; -+ for (i = 0; i < 8; i++) { -+ state->fpu.fx_tw |= (!env->fptags[i]) << i; -+ } -+ state->fpu.fx_opcode = env->fpop; -+ state->fpu.fx_ip.fa_64 = env->fpip; -+ state->fpu.fx_dp.fa_64 = env->fpdp; -+ state->fpu.fx_mxcsr = env->mxcsr; -+ state->fpu.fx_mxcsr_mask = 0x0000FFFF; -+ assert(sizeof(state->fpu.fx_87_ac) == sizeof(env->fpregs)); -+ memcpy(state->fpu.fx_87_ac, env->fpregs, sizeof(env->fpregs)); -+ for (i = 0; i < CPU_NB_REGS; i++) { -+ memcpy(&state->fpu.fx_xmm[i].xmm_bytes[0], -+ &env->xmm_regs[i].ZMM_Q(0), 8); -+ memcpy(&state->fpu.fx_xmm[i].xmm_bytes[8], -+ &env->xmm_regs[i].ZMM_Q(1), 8); -+ } -+ -+ /* MSRs. */ -+ state->msrs[NVMM_X64_MSR_EFER] = env->efer; -+ state->msrs[NVMM_X64_MSR_STAR] = env->star; -+#ifdef TARGET_X86_64 -+ state->msrs[NVMM_X64_MSR_LSTAR] = env->lstar; -+ state->msrs[NVMM_X64_MSR_CSTAR] = env->cstar; -+ state->msrs[NVMM_X64_MSR_SFMASK] = env->fmask; -+ state->msrs[NVMM_X64_MSR_KERNELGSBASE] = env->kernelgsbase; -+#endif -+ state->msrs[NVMM_X64_MSR_SYSENTER_CS] = env->sysenter_cs; -+ state->msrs[NVMM_X64_MSR_SYSENTER_ESP] = env->sysenter_esp; -+ state->msrs[NVMM_X64_MSR_SYSENTER_EIP] = env->sysenter_eip; -+ state->msrs[NVMM_X64_MSR_PAT] = env->pat; -+ state->msrs[NVMM_X64_MSR_TSC] = env->tsc; -+ -+ bitmap = -+ NVMM_X64_STATE_SEGS | -+ NVMM_X64_STATE_GPRS | -+ NVMM_X64_STATE_CRS | -+ NVMM_X64_STATE_DRS | -+ NVMM_X64_STATE_MSRS | -+ NVMM_X64_STATE_FPU; -+ -+ ret = nvmm_vcpu_setstate(mach, vcpu, bitmap); -+ if (ret == -1) { -+ error_report("NVMM: Failed to set virtual processor context," -+ " error=%d", errno); -+ } -+} -+ -+static void -+nvmm_get_segment(SegmentCache *qseg, const struct nvmm_x64_state_seg *nseg) -+{ -+ qseg->selector = nseg->selector; -+ qseg->limit = nseg->limit; -+ qseg->base = nseg->base; -+ -+ qseg->flags = -+ __SHIFTIN((uint32_t)nseg->attrib.type, DESC_TYPE_MASK) | -+ __SHIFTIN((uint32_t)nseg->attrib.s, DESC_S_MASK) | -+ __SHIFTIN((uint32_t)nseg->attrib.dpl, DESC_DPL_MASK) | -+ __SHIFTIN((uint32_t)nseg->attrib.p, DESC_P_MASK) | -+ __SHIFTIN((uint32_t)nseg->attrib.avl, DESC_AVL_MASK) | -+ __SHIFTIN((uint32_t)nseg->attrib.l, DESC_L_MASK) | -+ __SHIFTIN((uint32_t)nseg->attrib.def, DESC_B_MASK) | -+ __SHIFTIN((uint32_t)nseg->attrib.g, DESC_G_MASK); -+} -+ -+static void -+nvmm_get_registers(CPUState *cpu) -+{ -+ struct CPUX86State *env = (CPUArchState *)cpu->env_ptr; -+ struct nvmm_machine *mach = get_nvmm_mach(); -+ struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu); -+ struct nvmm_vcpu *vcpu = &qcpu->vcpu; -+ X86CPU *x86_cpu = X86_CPU(cpu); -+ struct nvmm_x64_state *state = vcpu->state; -+ uint64_t bitmap, tpr; -+ size_t i; -+ int ret; -+ -+ assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); -+ -+ bitmap = -+ NVMM_X64_STATE_SEGS | -+ NVMM_X64_STATE_GPRS | -+ NVMM_X64_STATE_CRS | -+ NVMM_X64_STATE_DRS | -+ NVMM_X64_STATE_MSRS | -+ NVMM_X64_STATE_FPU; -+ -+ ret = nvmm_vcpu_getstate(mach, vcpu, bitmap); -+ if (ret == -1) { -+ error_report("NVMM: Failed to get virtual processor context," -+ " error=%d", errno); -+ } -+ -+ /* GPRs. */ -+ env->regs[R_EAX] = state->gprs[NVMM_X64_GPR_RAX]; -+ env->regs[R_ECX] = state->gprs[NVMM_X64_GPR_RCX]; -+ env->regs[R_EDX] = state->gprs[NVMM_X64_GPR_RDX]; -+ env->regs[R_EBX] = state->gprs[NVMM_X64_GPR_RBX]; -+ env->regs[R_ESP] = state->gprs[NVMM_X64_GPR_RSP]; -+ env->regs[R_EBP] = state->gprs[NVMM_X64_GPR_RBP]; -+ env->regs[R_ESI] = state->gprs[NVMM_X64_GPR_RSI]; -+ env->regs[R_EDI] = state->gprs[NVMM_X64_GPR_RDI]; -+#ifdef TARGET_X86_64 -+ env->regs[R_R8] = state->gprs[NVMM_X64_GPR_R8]; -+ env->regs[R_R9] = state->gprs[NVMM_X64_GPR_R9]; -+ env->regs[R_R10] = state->gprs[NVMM_X64_GPR_R10]; -+ env->regs[R_R11] = state->gprs[NVMM_X64_GPR_R11]; -+ env->regs[R_R12] = state->gprs[NVMM_X64_GPR_R12]; -+ env->regs[R_R13] = state->gprs[NVMM_X64_GPR_R13]; -+ env->regs[R_R14] = state->gprs[NVMM_X64_GPR_R14]; -+ env->regs[R_R15] = state->gprs[NVMM_X64_GPR_R15]; -+#endif -+ -+ /* RIP and RFLAGS. */ -+ env->eip = state->gprs[NVMM_X64_GPR_RIP]; -+ env->eflags = state->gprs[NVMM_X64_GPR_RFLAGS]; -+ -+ /* Segments. */ -+ nvmm_get_segment(&env->segs[R_ES], &state->segs[NVMM_X64_SEG_ES]); -+ nvmm_get_segment(&env->segs[R_CS], &state->segs[NVMM_X64_SEG_CS]); -+ nvmm_get_segment(&env->segs[R_SS], &state->segs[NVMM_X64_SEG_SS]); -+ nvmm_get_segment(&env->segs[R_DS], &state->segs[NVMM_X64_SEG_DS]); -+ nvmm_get_segment(&env->segs[R_FS], &state->segs[NVMM_X64_SEG_FS]); -+ nvmm_get_segment(&env->segs[R_GS], &state->segs[NVMM_X64_SEG_GS]); -+ -+ /* Special segments. */ -+ nvmm_get_segment(&env->gdt, &state->segs[NVMM_X64_SEG_GDT]); -+ nvmm_get_segment(&env->ldt, &state->segs[NVMM_X64_SEG_LDT]); -+ nvmm_get_segment(&env->tr, &state->segs[NVMM_X64_SEG_TR]); -+ nvmm_get_segment(&env->idt, &state->segs[NVMM_X64_SEG_IDT]); -+ -+ /* Control registers. */ -+ env->cr[0] = state->crs[NVMM_X64_CR_CR0]; -+ env->cr[2] = state->crs[NVMM_X64_CR_CR2]; -+ env->cr[3] = state->crs[NVMM_X64_CR_CR3]; -+ env->cr[4] = state->crs[NVMM_X64_CR_CR4]; -+ tpr = state->crs[NVMM_X64_CR_CR8]; -+ if (tpr != qcpu->tpr) { -+ qcpu->tpr = tpr; -+ cpu_set_apic_tpr(x86_cpu->apic_state, tpr); -+ } -+ env->xcr0 = state->crs[NVMM_X64_CR_XCR0]; -+ -+ /* Debug registers. */ -+ env->dr[0] = state->drs[NVMM_X64_DR_DR0]; -+ env->dr[1] = state->drs[NVMM_X64_DR_DR1]; -+ env->dr[2] = state->drs[NVMM_X64_DR_DR2]; -+ env->dr[3] = state->drs[NVMM_X64_DR_DR3]; -+ env->dr[6] = state->drs[NVMM_X64_DR_DR6]; -+ env->dr[7] = state->drs[NVMM_X64_DR_DR7]; -+ -+ /* FPU. */ -+ env->fpuc = state->fpu.fx_cw; -+ env->fpstt = (state->fpu.fx_sw >> 11) & 0x7; -+ env->fpus = state->fpu.fx_sw & ~0x3800; -+ for (i = 0; i < 8; i++) { -+ env->fptags[i] = !((state->fpu.fx_tw >> i) & 1); -+ } -+ env->fpop = state->fpu.fx_opcode; -+ env->fpip = state->fpu.fx_ip.fa_64; -+ env->fpdp = state->fpu.fx_dp.fa_64; -+ env->mxcsr = state->fpu.fx_mxcsr; -+ assert(sizeof(state->fpu.fx_87_ac) == sizeof(env->fpregs)); -+ memcpy(env->fpregs, state->fpu.fx_87_ac, sizeof(env->fpregs)); -+ for (i = 0; i < CPU_NB_REGS; i++) { -+ memcpy(&env->xmm_regs[i].ZMM_Q(0), -+ &state->fpu.fx_xmm[i].xmm_bytes[0], 8); -+ memcpy(&env->xmm_regs[i].ZMM_Q(1), -+ &state->fpu.fx_xmm[i].xmm_bytes[8], 8); -+ } -+ -+ /* MSRs. */ -+ env->efer = state->msrs[NVMM_X64_MSR_EFER]; -+ env->star = state->msrs[NVMM_X64_MSR_STAR]; -+#ifdef TARGET_X86_64 -+ env->lstar = state->msrs[NVMM_X64_MSR_LSTAR]; -+ env->cstar = state->msrs[NVMM_X64_MSR_CSTAR]; -+ env->fmask = state->msrs[NVMM_X64_MSR_SFMASK]; -+ env->kernelgsbase = state->msrs[NVMM_X64_MSR_KERNELGSBASE]; -+#endif -+ env->sysenter_cs = state->msrs[NVMM_X64_MSR_SYSENTER_CS]; -+ env->sysenter_esp = state->msrs[NVMM_X64_MSR_SYSENTER_ESP]; -+ env->sysenter_eip = state->msrs[NVMM_X64_MSR_SYSENTER_EIP]; -+ env->pat = state->msrs[NVMM_X64_MSR_PAT]; -+ env->tsc = state->msrs[NVMM_X64_MSR_TSC]; -+ -+ x86_update_hflags(env); -+} -+ -+static bool -+nvmm_can_take_int(CPUState *cpu) -+{ -+ struct CPUX86State *env = (CPUArchState *)cpu->env_ptr; -+ struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu); -+ struct nvmm_vcpu *vcpu = &qcpu->vcpu; -+ struct nvmm_machine *mach = get_nvmm_mach(); -+ -+ if (qcpu->int_window_exit) { -+ return false; -+ } -+ -+ if (qcpu->int_shadow || !(env->eflags & IF_MASK)) { -+ struct nvmm_x64_state *state = vcpu->state; -+ -+ /* Exit on interrupt window. */ -+ nvmm_vcpu_getstate(mach, vcpu, NVMM_X64_STATE_INTR); -+ state->intr.int_window_exiting = 1; -+ nvmm_vcpu_setstate(mach, vcpu, NVMM_X64_STATE_INTR); -+ -+ return false; -+ } -+ -+ return true; -+} -+ -+static bool -+nvmm_can_take_nmi(CPUState *cpu) -+{ -+ struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu); -+ -+ /* -+ * Contrary to INTs, NMIs always schedule an exit when they are -+ * completed. Therefore, if window-exiting is enabled, it means -+ * NMIs are blocked. -+ */ -+ if (qcpu->nmi_window_exit) { -+ return false; -+ } -+ -+ return true; -+} -+ -+/* -+ * Called before the VCPU is run. We inject events generated by the I/O -+ * thread, and synchronize the guest TPR. -+ */ -+static void -+nvmm_vcpu_pre_run(CPUState *cpu) -+{ -+ struct CPUX86State *env = (CPUArchState *)cpu->env_ptr; -+ struct nvmm_machine *mach = get_nvmm_mach(); -+ struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu); -+ struct nvmm_vcpu *vcpu = &qcpu->vcpu; -+ X86CPU *x86_cpu = X86_CPU(cpu); -+ struct nvmm_x64_state *state = vcpu->state; -+ struct nvmm_vcpu_event *event = vcpu->event; -+ bool has_event = false; -+ bool sync_tpr = false; -+ uint8_t tpr; -+ int ret; -+ -+ qemu_mutex_lock_iothread(); -+ -+ tpr = cpu_get_apic_tpr(x86_cpu->apic_state); -+ if (tpr != qcpu->tpr) { -+ qcpu->tpr = tpr; -+ sync_tpr = true; -+ } -+ -+ /* -+ * Force the VCPU out of its inner loop to process any INIT requests -+ * or commit pending TPR access. -+ */ -+ if (cpu->interrupt_request & (CPU_INTERRUPT_INIT | CPU_INTERRUPT_TPR)) { -+ cpu->exit_request = 1; -+ } -+ -+ if (!has_event && (cpu->interrupt_request & CPU_INTERRUPT_NMI)) { -+ if (nvmm_can_take_nmi(cpu)) { -+ cpu->interrupt_request &= ~CPU_INTERRUPT_NMI; -+ event->type = NVMM_VCPU_EVENT_INTR; -+ event->vector = 2; -+ has_event = true; -+ } -+ } -+ -+ if (!has_event && (cpu->interrupt_request & CPU_INTERRUPT_HARD)) { -+ if (nvmm_can_take_int(cpu)) { -+ cpu->interrupt_request &= ~CPU_INTERRUPT_HARD; -+ event->type = NVMM_VCPU_EVENT_INTR; -+ event->vector = cpu_get_pic_interrupt(env); -+ has_event = true; -+ } -+ } -+ -+ /* Don't want SMIs. */ -+ if (cpu->interrupt_request & CPU_INTERRUPT_SMI) { -+ cpu->interrupt_request &= ~CPU_INTERRUPT_SMI; -+ } -+ -+ if (sync_tpr) { -+ ret = nvmm_vcpu_getstate(mach, vcpu, NVMM_X64_STATE_CRS); -+ if (ret == -1) { -+ error_report("NVMM: Failed to get CPU state," -+ " error=%d", errno); -+ } -+ -+ state->crs[NVMM_X64_CR_CR8] = qcpu->tpr; -+ -+ ret = nvmm_vcpu_setstate(mach, vcpu, NVMM_X64_STATE_CRS); -+ if (ret == -1) { -+ error_report("NVMM: Failed to set CPU state," -+ " error=%d", errno); -+ } -+ } -+ -+ if (has_event) { -+ ret = nvmm_vcpu_inject(mach, vcpu); -+ if (ret == -1) { -+ error_report("NVMM: Failed to inject event," -+ " error=%d", errno); -+ } -+ } -+ -+ qemu_mutex_unlock_iothread(); -+} -+ -+/* -+ * Called after the VCPU ran. We synchronize the host view of the TPR and -+ * RFLAGS. -+ */ -+static void -+nvmm_vcpu_post_run(CPUState *cpu, struct nvmm_vcpu_exit *exit) -+{ -+ struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu); -+ struct CPUX86State *env = (CPUArchState *)cpu->env_ptr; -+ X86CPU *x86_cpu = X86_CPU(cpu); -+ uint64_t tpr; -+ -+ env->eflags = exit->exitstate.rflags; -+ qcpu->int_shadow = exit->exitstate.int_shadow; -+ qcpu->int_window_exit = exit->exitstate.int_window_exiting; -+ qcpu->nmi_window_exit = exit->exitstate.nmi_window_exiting; -+ -+ tpr = exit->exitstate.cr8; -+ if (qcpu->tpr != tpr) { -+ qcpu->tpr = tpr; -+ qemu_mutex_lock_iothread(); -+ cpu_set_apic_tpr(x86_cpu->apic_state, qcpu->tpr); -+ qemu_mutex_unlock_iothread(); -+ } -+} -+ -+/* -------------------------------------------------------------------------- */ -+ -+static void -+nvmm_io_callback(struct nvmm_io *io) -+{ -+ MemTxAttrs attrs = { 0 }; -+ int ret; -+ -+ ret = address_space_rw(&address_space_io, io->port, attrs, io->data, -+ io->size, !io->in); -+ if (ret != MEMTX_OK) { -+ error_report("NVMM: I/O Transaction Failed " -+ "[%s, port=%u, size=%zu]", (io->in ? "in" : "out"), -+ io->port, io->size); -+ } -+ -+ /* Needed, otherwise infinite loop. */ -+ current_cpu->vcpu_dirty = false; -+} -+ -+static void -+nvmm_mem_callback(struct nvmm_mem *mem) -+{ -+ cpu_physical_memory_rw(mem->gpa, mem->data, mem->size, mem->write); -+ -+ /* Needed, otherwise infinite loop. */ -+ current_cpu->vcpu_dirty = false; -+} -+ -+static struct nvmm_assist_callbacks nvmm_callbacks = { -+ .io = nvmm_io_callback, -+ .mem = nvmm_mem_callback -+}; -+ -+/* -------------------------------------------------------------------------- */ -+ -+static int -+nvmm_handle_mem(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) -+{ -+ int ret; -+ -+ ret = nvmm_assist_mem(mach, vcpu); -+ if (ret == -1) { -+ error_report("NVMM: Mem Assist Failed [gpa=%p]", -+ (void *)vcpu->exit->u.mem.gpa); -+ } -+ -+ return ret; -+} -+ -+static int -+nvmm_handle_io(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) -+{ -+ int ret; -+ -+ ret = nvmm_assist_io(mach, vcpu); -+ if (ret == -1) { -+ error_report("NVMM: I/O Assist Failed [port=%d]", -+ (int)vcpu->exit->u.io.port); -+ } -+ -+ return ret; -+} -+ -+static int -+nvmm_handle_rdmsr(struct nvmm_machine *mach, CPUState *cpu, -+ struct nvmm_vcpu_exit *exit) -+{ -+ struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu); -+ struct nvmm_vcpu *vcpu = &qcpu->vcpu; -+ X86CPU *x86_cpu = X86_CPU(cpu); -+ struct nvmm_x64_state *state = vcpu->state; -+ uint64_t val; -+ int ret; -+ -+ switch (exit->u.rdmsr.msr) { -+ case MSR_IA32_APICBASE: -+ val = cpu_get_apic_base(x86_cpu->apic_state); -+ break; -+ case MSR_MTRRcap: -+ case MSR_MTRRdefType: -+ case MSR_MCG_CAP: -+ case MSR_MCG_STATUS: -+ val = 0; -+ break; -+ default: /* More MSRs to add? */ -+ val = 0; -+ error_report("NVMM: Unexpected RDMSR 0x%x, ignored", -+ exit->u.rdmsr.msr); -+ break; -+ } -+ -+ ret = nvmm_vcpu_getstate(mach, vcpu, NVMM_X64_STATE_GPRS); -+ if (ret == -1) { -+ return -1; -+ } -+ -+ state->gprs[NVMM_X64_GPR_RAX] = (val & 0xFFFFFFFF); -+ state->gprs[NVMM_X64_GPR_RDX] = (val >> 32); -+ state->gprs[NVMM_X64_GPR_RIP] = exit->u.rdmsr.npc; -+ -+ ret = nvmm_vcpu_setstate(mach, vcpu, NVMM_X64_STATE_GPRS); -+ if (ret == -1) { -+ return -1; -+ } -+ -+ return 0; -+} -+ -+static int -+nvmm_handle_wrmsr(struct nvmm_machine *mach, CPUState *cpu, -+ struct nvmm_vcpu_exit *exit) -+{ -+ struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu); -+ struct nvmm_vcpu *vcpu = &qcpu->vcpu; -+ X86CPU *x86_cpu = X86_CPU(cpu); -+ struct nvmm_x64_state *state = vcpu->state; -+ uint64_t val; -+ int ret; -+ -+ val = exit->u.wrmsr.val; -+ -+ switch (exit->u.wrmsr.msr) { -+ case MSR_IA32_APICBASE: -+ cpu_set_apic_base(x86_cpu->apic_state, val); -+ break; -+ case MSR_MTRRdefType: -+ case MSR_MCG_STATUS: -+ break; -+ default: /* More MSRs to add? */ -+ error_report("NVMM: Unexpected WRMSR 0x%x [val=0x%lx], ignored", -+ exit->u.wrmsr.msr, val); -+ break; -+ } -+ -+ ret = nvmm_vcpu_getstate(mach, vcpu, NVMM_X64_STATE_GPRS); -+ if (ret == -1) { -+ return -1; -+ } -+ -+ state->gprs[NVMM_X64_GPR_RIP] = exit->u.wrmsr.npc; -+ -+ ret = nvmm_vcpu_setstate(mach, vcpu, NVMM_X64_STATE_GPRS); -+ if (ret == -1) { -+ return -1; -+ } -+ -+ return 0; -+} -+ -+static int -+nvmm_handle_halted(struct nvmm_machine *mach, CPUState *cpu, -+ struct nvmm_vcpu_exit *exit) -+{ -+ struct CPUX86State *env = (CPUArchState *)cpu->env_ptr; -+ int ret = 0; -+ -+ qemu_mutex_lock_iothread(); -+ -+ if (!((cpu->interrupt_request & CPU_INTERRUPT_HARD) && -+ (env->eflags & IF_MASK)) && -+ !(cpu->interrupt_request & CPU_INTERRUPT_NMI)) { -+ cpu->exception_index = EXCP_HLT; -+ cpu->halted = true; -+ ret = 1; -+ } -+ -+ qemu_mutex_unlock_iothread(); -+ -+ return ret; -+} -+ -+static int -+nvmm_inject_ud(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) -+{ -+ struct nvmm_vcpu_event *event = vcpu->event; -+ -+ event->type = NVMM_VCPU_EVENT_EXCP; -+ event->vector = 6; -+ event->u.excp.error = 0; -+ -+ return nvmm_vcpu_inject(mach, vcpu); -+} -+ -+static int -+nvmm_vcpu_loop(CPUState *cpu) -+{ -+ struct CPUX86State *env = (CPUArchState *)cpu->env_ptr; -+ struct nvmm_machine *mach = get_nvmm_mach(); -+ struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu); -+ struct nvmm_vcpu *vcpu = &qcpu->vcpu; -+ X86CPU *x86_cpu = X86_CPU(cpu); -+ struct nvmm_vcpu_exit *exit = vcpu->exit; -+ int ret; -+ -+ /* -+ * Some asynchronous events must be handled outside of the inner -+ * VCPU loop. They are handled here. -+ */ -+ if (cpu->interrupt_request & CPU_INTERRUPT_INIT) { -+ nvmm_cpu_synchronize_state(cpu); -+ do_cpu_init(x86_cpu); -+ /* set int/nmi windows back to the reset state */ -+ } -+ if (cpu->interrupt_request & CPU_INTERRUPT_POLL) { -+ cpu->interrupt_request &= ~CPU_INTERRUPT_POLL; -+ apic_poll_irq(x86_cpu->apic_state); -+ } -+ if (((cpu->interrupt_request & CPU_INTERRUPT_HARD) && -+ (env->eflags & IF_MASK)) || -+ (cpu->interrupt_request & CPU_INTERRUPT_NMI)) { -+ cpu->halted = false; -+ } -+ if (cpu->interrupt_request & CPU_INTERRUPT_SIPI) { -+ nvmm_cpu_synchronize_state(cpu); -+ do_cpu_sipi(x86_cpu); -+ } -+ if (cpu->interrupt_request & CPU_INTERRUPT_TPR) { -+ cpu->interrupt_request &= ~CPU_INTERRUPT_TPR; -+ nvmm_cpu_synchronize_state(cpu); -+ apic_handle_tpr_access_report(x86_cpu->apic_state, env->eip, -+ env->tpr_access_type); -+ } -+ -+ if (cpu->halted) { -+ cpu->exception_index = EXCP_HLT; -+ qatomic_set(&cpu->exit_request, false); -+ return 0; -+ } -+ -+ qemu_mutex_unlock_iothread(); -+ cpu_exec_start(cpu); -+ -+ /* -+ * Inner VCPU loop. -+ */ -+ do { -+ if (cpu->vcpu_dirty) { -+ nvmm_set_registers(cpu); -+ cpu->vcpu_dirty = false; -+ } -+ -+ if (qcpu->stop) { -+ cpu->exception_index = EXCP_INTERRUPT; -+ qcpu->stop = false; -+ ret = 1; -+ break; -+ } -+ -+ nvmm_vcpu_pre_run(cpu); -+ -+ if (qatomic_read(&cpu->exit_request)) { -+#if NVMM_USER_VERSION >= 2 -+ nvmm_vcpu_stop(vcpu); -+#else -+ qemu_cpu_kick_self(); -+#endif -+ } -+ -+ /* Read exit_request before the kernel reads the immediate exit flag */ -+ smp_rmb(); -+ ret = nvmm_vcpu_run(mach, vcpu); -+ if (ret == -1) { -+ error_report("NVMM: Failed to exec a virtual processor," -+ " error=%d", errno); -+ break; -+ } -+ -+ nvmm_vcpu_post_run(cpu, exit); -+ -+ switch (exit->reason) { -+ case NVMM_VCPU_EXIT_NONE: -+ break; -+#if NVMM_USER_VERSION >= 2 -+ case NVMM_VCPU_EXIT_STOPPED: -+ /* -+ * The kernel cleared the immediate exit flag; cpu->exit_request -+ * must be cleared after -+ */ -+ smp_wmb(); -+ qcpu->stop = true; -+ break; -+#endif -+ case NVMM_VCPU_EXIT_MEMORY: -+ ret = nvmm_handle_mem(mach, vcpu); -+ break; -+ case NVMM_VCPU_EXIT_IO: -+ ret = nvmm_handle_io(mach, vcpu); -+ break; -+ case NVMM_VCPU_EXIT_INT_READY: -+ case NVMM_VCPU_EXIT_NMI_READY: -+ case NVMM_VCPU_EXIT_TPR_CHANGED: -+ break; -+ case NVMM_VCPU_EXIT_HALTED: -+ ret = nvmm_handle_halted(mach, cpu, exit); -+ break; -+ case NVMM_VCPU_EXIT_SHUTDOWN: -+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); -+ cpu->exception_index = EXCP_INTERRUPT; -+ ret = 1; -+ break; -+ case NVMM_VCPU_EXIT_RDMSR: -+ ret = nvmm_handle_rdmsr(mach, cpu, exit); -+ break; -+ case NVMM_VCPU_EXIT_WRMSR: -+ ret = nvmm_handle_wrmsr(mach, cpu, exit); -+ break; -+ case NVMM_VCPU_EXIT_MONITOR: -+ case NVMM_VCPU_EXIT_MWAIT: -+ ret = nvmm_inject_ud(mach, vcpu); -+ break; -+ default: -+ error_report("NVMM: Unexpected VM exit code 0x%lx [hw=0x%lx]", -+ exit->reason, exit->u.inv.hwcode); -+ nvmm_get_registers(cpu); -+ qemu_mutex_lock_iothread(); -+ qemu_system_guest_panicked(cpu_get_crash_info(cpu)); -+ qemu_mutex_unlock_iothread(); -+ ret = -1; -+ break; -+ } -+ } while (ret == 0); -+ -+ cpu_exec_end(cpu); -+ qemu_mutex_lock_iothread(); -+ -+ qatomic_set(&cpu->exit_request, false); -+ -+ return ret < 0; -+} -+ -+/* -------------------------------------------------------------------------- */ -+ -+static void -+do_nvmm_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg) -+{ -+ nvmm_get_registers(cpu); -+ cpu->vcpu_dirty = true; -+} -+ -+static void -+do_nvmm_cpu_synchronize_post_reset(CPUState *cpu, run_on_cpu_data arg) -+{ -+ nvmm_set_registers(cpu); -+ cpu->vcpu_dirty = false; -+} -+ -+static void -+do_nvmm_cpu_synchronize_post_init(CPUState *cpu, run_on_cpu_data arg) -+{ -+ nvmm_set_registers(cpu); -+ cpu->vcpu_dirty = false; -+} -+ -+static void -+do_nvmm_cpu_synchronize_pre_loadvm(CPUState *cpu, run_on_cpu_data arg) -+{ -+ cpu->vcpu_dirty = true; -+} -+ -+void nvmm_cpu_synchronize_state(CPUState *cpu) -+{ -+ if (!cpu->vcpu_dirty) { -+ run_on_cpu(cpu, do_nvmm_cpu_synchronize_state, RUN_ON_CPU_NULL); -+ } -+} -+ -+void nvmm_cpu_synchronize_post_reset(CPUState *cpu) -+{ -+ run_on_cpu(cpu, do_nvmm_cpu_synchronize_post_reset, RUN_ON_CPU_NULL); -+} -+ -+void nvmm_cpu_synchronize_post_init(CPUState *cpu) -+{ -+ run_on_cpu(cpu, do_nvmm_cpu_synchronize_post_init, RUN_ON_CPU_NULL); -+} -+ -+void nvmm_cpu_synchronize_pre_loadvm(CPUState *cpu) -+{ -+ run_on_cpu(cpu, do_nvmm_cpu_synchronize_pre_loadvm, RUN_ON_CPU_NULL); -+} -+ -+/* -------------------------------------------------------------------------- */ -+ -+static Error *nvmm_migration_blocker; -+ -+/* -+ * The nvmm_vcpu_stop() mechanism breaks races between entering the VMM -+ * and another thread signaling the vCPU thread to exit. -+ */ -+ -+static void -+nvmm_ipi_signal(int sigcpu) -+{ -+ if (current_cpu) { -+ struct qemu_vcpu *qcpu = get_qemu_vcpu(current_cpu); -+#if NVMM_USER_VERSION >= 2 -+ struct nvmm_vcpu *vcpu = &qcpu->vcpu; -+ nvmm_vcpu_stop(vcpu); -+#else -+ qcpu->stop = true; -+#endif -+ } -+} -+ -+static void -+nvmm_init_cpu_signals(void) -+{ -+ struct sigaction sigact; -+ sigset_t set; -+ -+ /* Install the IPI handler. */ -+ memset(&sigact, 0, sizeof(sigact)); -+ sigact.sa_handler = nvmm_ipi_signal; -+ sigaction(SIG_IPI, &sigact, NULL); -+ -+ /* Allow IPIs on the current thread. */ -+ sigprocmask(SIG_BLOCK, NULL, &set); -+ sigdelset(&set, SIG_IPI); -+ pthread_sigmask(SIG_SETMASK, &set, NULL); -+} -+ -+int -+nvmm_init_vcpu(CPUState *cpu) -+{ -+ struct nvmm_machine *mach = get_nvmm_mach(); -+ struct nvmm_vcpu_conf_cpuid cpuid; -+ struct nvmm_vcpu_conf_tpr tpr; -+ Error *local_error = NULL; -+ struct qemu_vcpu *qcpu; -+ int ret, err; -+ -+ nvmm_init_cpu_signals(); -+ -+ if (nvmm_migration_blocker == NULL) { -+ error_setg(&nvmm_migration_blocker, -+ "NVMM: Migration not supported"); -+ -+ (void)migrate_add_blocker(nvmm_migration_blocker, &local_error); -+ if (local_error) { -+ error_report_err(local_error); -+ migrate_del_blocker(nvmm_migration_blocker); -+ error_free(nvmm_migration_blocker); -+ return -EINVAL; -+ } -+ } -+ -+ qcpu = g_malloc0(sizeof(*qcpu)); -+ if (qcpu == NULL) { -+ error_report("NVMM: Failed to allocate VCPU context."); -+ return -ENOMEM; -+ } -+ -+ ret = nvmm_vcpu_create(mach, cpu->cpu_index, &qcpu->vcpu); -+ if (ret == -1) { -+ err = errno; -+ error_report("NVMM: Failed to create a virtual processor," -+ " error=%d", err); -+ g_free(qcpu); -+ return -err; -+ } -+ -+ memset(&cpuid, 0, sizeof(cpuid)); -+ cpuid.mask = 1; -+ cpuid.leaf = 0x00000001; -+ cpuid.u.mask.set.edx = CPUID_MCE | CPUID_MCA | CPUID_MTRR; -+ ret = nvmm_vcpu_configure(mach, &qcpu->vcpu, NVMM_VCPU_CONF_CPUID, -+ &cpuid); -+ if (ret == -1) { -+ err = errno; -+ error_report("NVMM: Failed to configure a virtual processor," -+ " error=%d", err); -+ g_free(qcpu); -+ return -err; -+ } -+ -+ ret = nvmm_vcpu_configure(mach, &qcpu->vcpu, NVMM_VCPU_CONF_CALLBACKS, -+ &nvmm_callbacks); -+ if (ret == -1) { -+ err = errno; -+ error_report("NVMM: Failed to configure a virtual processor," -+ " error=%d", err); -+ g_free(qcpu); -+ return -err; -+ } -+ -+ if (qemu_mach.cap.arch.vcpu_conf_support & NVMM_CAP_ARCH_VCPU_CONF_TPR) { -+ memset(&tpr, 0, sizeof(tpr)); -+ tpr.exit_changed = 1; -+ ret = nvmm_vcpu_configure(mach, &qcpu->vcpu, NVMM_VCPU_CONF_TPR, &tpr); -+ if (ret == -1) { -+ err = errno; -+ error_report("NVMM: Failed to configure a virtual processor," -+ " error=%d", err); -+ g_free(qcpu); -+ return -err; -+ } -+ } -+ -+ cpu->vcpu_dirty = true; -+ cpu->hax_vcpu = (struct hax_vcpu_state *)qcpu; -+ -+ return 0; -+} -+ -+int -+nvmm_vcpu_exec(CPUState *cpu) -+{ -+ int ret, fatal; -+ -+ while (1) { -+ if (cpu->exception_index >= EXCP_INTERRUPT) { -+ ret = cpu->exception_index; -+ cpu->exception_index = -1; -+ break; -+ } -+ -+ fatal = nvmm_vcpu_loop(cpu); -+ -+ if (fatal) { -+ error_report("NVMM: Failed to execute a VCPU."); -+ abort(); -+ } -+ } -+ -+ return ret; -+} -+ -+void -+nvmm_destroy_vcpu(CPUState *cpu) -+{ -+ struct nvmm_machine *mach = get_nvmm_mach(); -+ struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu); -+ -+ nvmm_vcpu_destroy(mach, &qcpu->vcpu); -+ g_free(cpu->hax_vcpu); -+} -+ -+/* -------------------------------------------------------------------------- */ -+ -+static void -+nvmm_update_mapping(hwaddr start_pa, ram_addr_t size, uintptr_t hva, -+ bool add, bool rom, const char *name) -+{ -+ struct nvmm_machine *mach = get_nvmm_mach(); -+ int ret, prot; -+ -+ if (add) { -+ prot = PROT_READ | PROT_EXEC; -+ if (!rom) { -+ prot |= PROT_WRITE; -+ } -+ ret = nvmm_gpa_map(mach, hva, start_pa, size, prot); -+ } else { -+ ret = nvmm_gpa_unmap(mach, hva, start_pa, size); -+ } -+ -+ if (ret == -1) { -+ error_report("NVMM: Failed to %s GPA range '%s' PA:%p, " -+ "Size:%p bytes, HostVA:%p, error=%d", -+ (add ? "map" : "unmap"), name, (void *)(uintptr_t)start_pa, -+ (void *)size, (void *)hva, errno); -+ } -+} -+ -+static void -+nvmm_process_section(MemoryRegionSection *section, int add) -+{ -+ MemoryRegion *mr = section->mr; -+ hwaddr start_pa = section->offset_within_address_space; -+ ram_addr_t size = int128_get64(section->size); -+ unsigned int delta; -+ uintptr_t hva; -+ -+ if (!memory_region_is_ram(mr)) { -+ return; -+ } -+ -+ /* Adjust start_pa and size so that they are page-aligned. */ -+ delta = qemu_real_host_page_size - (start_pa & ~qemu_real_host_page_mask); -+ delta &= ~qemu_real_host_page_mask; -+ if (delta > size) { -+ return; -+ } -+ start_pa += delta; -+ size -= delta; -+ size &= qemu_real_host_page_mask; -+ if (!size || (start_pa & ~qemu_real_host_page_mask)) { -+ return; -+ } -+ -+ hva = (uintptr_t)memory_region_get_ram_ptr(mr) + -+ section->offset_within_region + delta; -+ -+ nvmm_update_mapping(start_pa, size, hva, add, -+ memory_region_is_rom(mr), mr->name); -+} -+ -+static void -+nvmm_region_add(MemoryListener *listener, MemoryRegionSection *section) -+{ -+ memory_region_ref(section->mr); -+ nvmm_process_section(section, 1); -+} -+ -+static void -+nvmm_region_del(MemoryListener *listener, MemoryRegionSection *section) -+{ -+ nvmm_process_section(section, 0); -+ memory_region_unref(section->mr); -+} -+ -+static void -+nvmm_transaction_begin(MemoryListener *listener) -+{ -+ /* nothing */ -+} -+ -+static void -+nvmm_transaction_commit(MemoryListener *listener) -+{ -+ /* nothing */ -+} -+ -+static void -+nvmm_log_sync(MemoryListener *listener, MemoryRegionSection *section) -+{ -+ MemoryRegion *mr = section->mr; -+ -+ if (!memory_region_is_ram(mr)) { -+ return; -+ } -+ -+ memory_region_set_dirty(mr, 0, int128_get64(section->size)); -+} -+ -+static MemoryListener nvmm_memory_listener = { -+ .begin = nvmm_transaction_begin, -+ .commit = nvmm_transaction_commit, -+ .region_add = nvmm_region_add, -+ .region_del = nvmm_region_del, -+ .log_sync = nvmm_log_sync, -+ .priority = 10, -+}; -+ -+static void -+nvmm_ram_block_added(RAMBlockNotifier *n, void *host, size_t size) -+{ -+ struct nvmm_machine *mach = get_nvmm_mach(); -+ uintptr_t hva = (uintptr_t)host; -+ int ret; -+ -+ ret = nvmm_hva_map(mach, hva, size); -+ -+ if (ret == -1) { -+ error_report("NVMM: Failed to map HVA, HostVA:%p " -+ "Size:%p bytes, error=%d", -+ (void *)hva, (void *)size, errno); -+ } -+} -+ -+static struct RAMBlockNotifier nvmm_ram_notifier = { -+ .ram_block_added = nvmm_ram_block_added -+}; -+ -+/* -------------------------------------------------------------------------- */ -+ -+static int -+nvmm_accel_init(MachineState *ms) -+{ -+ int ret, err; -+ -+ ret = nvmm_init(); -+ if (ret == -1) { -+ err = errno; -+ error_report("NVMM: Initialization failed, error=%d", errno); -+ return -err; -+ } -+ -+ ret = nvmm_capability(&qemu_mach.cap); -+ if (ret == -1) { -+ err = errno; -+ error_report("NVMM: Unable to fetch capability, error=%d", errno); -+ return -err; -+ } -+ if (qemu_mach.cap.version < NVMM_KERN_VERSION) { -+ error_report("NVMM: Unsupported version %u", qemu_mach.cap.version); -+ return -EPROGMISMATCH; -+ } -+ if (qemu_mach.cap.state_size != sizeof(struct nvmm_x64_state)) { -+ error_report("NVMM: Wrong state size %u", qemu_mach.cap.state_size); -+ return -EPROGMISMATCH; -+ } -+ -+ ret = nvmm_machine_create(&qemu_mach.mach); -+ if (ret == -1) { -+ err = errno; -+ error_report("NVMM: Machine creation failed, error=%d", errno); -+ return -err; -+ } -+ -+ memory_listener_register(&nvmm_memory_listener, &address_space_memory); -+ ram_block_notifier_add(&nvmm_ram_notifier); -+ -+ printf("NetBSD Virtual Machine Monitor accelerator is operational\n"); -+ return 0; -+} -+ -+int -+nvmm_enabled(void) -+{ -+ return nvmm_allowed; -+} -+ -+static void -+nvmm_accel_class_init(ObjectClass *oc, void *data) -+{ -+ AccelClass *ac = ACCEL_CLASS(oc); -+ ac->name = "NVMM"; -+ ac->init_machine = nvmm_accel_init; -+ ac->allowed = &nvmm_allowed; -+} -+ -+static const TypeInfo nvmm_accel_type = { -+ .name = ACCEL_CLASS_NAME("nvmm"), -+ .parent = TYPE_ACCEL, -+ .class_init = nvmm_accel_class_init, -+}; -+ -+static void -+nvmm_type_init(void) -+{ -+ type_register_static(&nvmm_accel_type); -+} -+ -+type_init(nvmm_type_init); |