Home | History | Annotate | Line # | Download | only in aarch64
      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