1 /* $NetBSD: vmt.c,v 1.3 2026/09/12 12:47:59 skrll Exp $ */ 2 3 /* 4 * Copyright (c) 2024 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #ifdef _KERNEL_OPT 34 #include "acpica.h" 35 #endif 36 37 #include <sys/device.h> 38 #include <sys/module.h> 39 #include <sys/systm.h> 40 41 #if NACPICA > 0 42 #include <dev/acpi/acpivar.h> 43 #endif 44 45 #include <dev/vmt/vmtreg.h> 46 #include <dev/vmt/vmtvar.h> 47 48 static int vmt_match(device_t, cfdata_t, void *); 49 static void vmt_attach(device_t, device_t, void *); 50 static int vmt_detach(device_t, int); 51 52 CFATTACH_DECL_NEW(vmt, sizeof(struct vmt_softc), 53 vmt_match, vmt_attach, vmt_detach, NULL); 54 55 static bool vmt_attached = false; 56 57 static int 58 vmt_match(device_t parent, cfdata_t match, void *aux) 59 { 60 /* vmt should not attach to more than a single CPU. */ 61 if (vmt_attached) 62 return 0; 63 64 #if NACPICA > 0 65 /* 66 * The backdoor is a read of MDCCSR_EL0 with a magic value in x7. 67 * Probe only when the firmware names VMware; a hypervisor that 68 * names something else, or nothing, is not one whose API this 69 * driver knows, and there is nothing to find. (QEMU 11.1 under 70 * hvf also trapped the read as an undefined instruction, which is 71 * fatal in kernel mode. That was a QEMU bug, since fixed.) See 72 * port-arm/60655. 73 */ 74 char hv[sizeof(AcpiGbl_FADT.HypervisorId) + 1]; 75 if (!acpi_fadt_hypervisor_id(hv, sizeof(hv)) || 76 strncmp(hv, "VMware", 6) != 0) 77 return 0; 78 #endif 79 80 return vmt_probe(); 81 } 82 83 static void 84 vmt_attach(device_t parent, device_t self, void *aux) 85 { 86 struct vmt_softc *sc = device_private(self); 87 88 aprint_naive("\n"); 89 aprint_normal(": VMware Tools driver\n"); 90 91 sc->sc_dev = self; 92 vmt_common_attach(sc); 93 94 vmt_attached = true; 95 } 96 97 static int 98 vmt_detach(device_t self, int flags) 99 { 100 struct vmt_softc *sc = device_private(self); 101 int rv; 102 103 rv = vmt_common_detach(sc); 104 if (rv != 0) 105 return rv; 106 107 vmt_attached = false; 108 return 0; 109 } 110 111 MODULE(MODULE_CLASS_DRIVER, vmt, "sysmon_power,sysmon_taskq"); 112 113 #ifdef _MODULE 114 #include "ioconf.c" 115 #endif 116 117 static int 118 vmt_modcmd(modcmd_t cmd, void *aux) 119 { 120 int error = 0; 121 122 switch (cmd) { 123 case MODULE_CMD_INIT: 124 #ifdef _MODULE 125 error = config_init_component(cfdriver_ioconf_vmt, 126 cfattach_ioconf_vmt, cfdata_ioconf_vmt); 127 #endif 128 break; 129 case MODULE_CMD_FINI: 130 #ifdef _MODULE 131 error = config_fini_component(cfdriver_ioconf_vmt, 132 cfattach_ioconf_vmt, cfdata_ioconf_vmt); 133 #endif 134 break; 135 case MODULE_CMD_AUTOUNLOAD: 136 error = EBUSY; 137 break; 138 default: 139 error = ENOTTY; 140 break; 141 } 142 143 return error; 144 } 145