NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: port-arm/60655: vmt(4) probes the VMware backdoor unconditionally on aarch64 and panics the kernel on hypervisors that do not implement it
The following reply was made to PR port-arm/60655; it has been noted by GNATS.
From: zakinko%snowrabbit.org@localhost
To: gnats-bugs%NetBSD.org@localhost
Cc: port-arm-maintainer%NetBSD.org@localhost, netbsd-bugs%NetBSD.org@localhost,
gnats-admin%NetBSD.org@localhost, skrll%NetBSD.org@localhost, zakinko%snowrabbit.org@localhost
Subject: Re: port-arm/60655: vmt(4) probes the VMware backdoor unconditionally on aarch64 and panics the kernel on hypervisors that do not implement it
Date: Sun, 6 Sep 2026 11:42:58 +0900 (JST)
Thanks for the pointer to HypervisorId -- that was the right place to look.
I have rewritten the patch to read the FADT instead: the old version let
the probe run and recovered from the trap, while this one never executes
the instruction. On stock QEMU 11.1.0 (-M virt -accel hvf) the guest
reaches login with no hvf_unhandled_sysreg_read firing, where the old patch
left one trap per boot.
I checked all three cases on real hypervisors, not QEMU alone. On VMware
Fusion 26 (Apple Silicon), with the same kernel:
HypervisorId = 0x0000657261774d56 = "VMware"
vmt0 at cpu0: VMware Tools driver
vmt0: UUID: 564de88b-...
so the comparison matches a real VMware guest and vmt(4) attaches and talks
to the backdoor as before. With the FADT string forced to "VMware" or left
at zero on QEMU, vmt_probe() still runs (and panics there, since that QEMU
refuses MDCCSR_EL0) -- so the check is not just disabling vmt(4), and a
hypervisor that leaves the field empty keeps the old behaviour.
Let me know if this isn't the shape you had in mind.
--- sys/arch/aarch64/aarch64/vmt.c.orig
+++ sys/arch/aarch64/aarch64/vmt.c
@@ -32,7 +32,16 @@
#include <sys/device.h>
#include <sys/module.h>
+#include <sys/systm.h>
+#ifdef _KERNEL_OPT
+#include "acpica.h"
+#endif
+
+#if NACPICA > 0
+#include <dev/acpi/acpivar.h>
+#endif
+
#include <dev/vmt/vmtreg.h>
#include <dev/vmt/vmtvar.h>
@@ -45,6 +54,39 @@
static bool vmt_attached = false;
+#if NACPICA > 0
+/*
+ * The ACPI 6.0 FADT carries a Hypervisor Vendor Identity: eight bytes of
+ * ASCII, NUL padded. Skip the probe when the hypervisor identifies
+ * itself as something other than VMware; there is nothing there to find.
+ *
+ * On aarch64 the backdoor is a read of MDCCSR_EL0 with a magic value in
+ * x7. The register is architecturally mandatory, but a hypervisor is
+ * free to trap it and answer with an undefined instruction rather than a
+ * value, and that trap is fatal in kernel mode. QEMU 11.1 does exactly
+ * this once the Apple vGIC is in use, so the machine panics during
+ * autoconfiguration. See port-arm/60655.
+ *
+ * Firmware that leaves the field zero tells us nothing, so probe as
+ * before. The bytes are compared in table order rather than through the
+ * UINT64, so that this reads the same on aarch64eb.
+ */
+static bool
+vmt_hypervisor_may_be_vmware(void)
+{
+ char name[sizeof(AcpiGbl_FADT.HypervisorId) + 1];
+
+ if (AcpiGbl_FADT.HypervisorId == 0)
+ return true;
+
+ memcpy(name, &AcpiGbl_FADT.HypervisorId,
+ sizeof(AcpiGbl_FADT.HypervisorId));
+ name[sizeof(name) - 1] = '\0';
+
+ return strncmp(name, "VMware", 6) == 0;
+}
+#endif /* NACPICA > 0 */
+
static int
vmt_match(device_t parent, cfdata_t match, void *aux)
{
@@ -52,6 +94,11 @@
if (vmt_attached)
return 0;
+#if NACPICA > 0
+ if (!vmt_hypervisor_may_be_vmware())
+ return 0;
+#endif
+
return vmt_probe();
}
Home |
Main Index |
Thread Index |
Old Index