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



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