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