cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vmci_driver.c (4148B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * VMware VMCI Driver
      4 *
      5 * Copyright (C) 2012 VMware, Inc. All rights reserved.
      6 */
      7
      8#include <linux/vmw_vmci_defs.h>
      9#include <linux/vmw_vmci_api.h>
     10#include <linux/atomic.h>
     11#include <linux/kernel.h>
     12#include <linux/module.h>
     13#include <linux/init.h>
     14
     15#include "vmci_driver.h"
     16#include "vmci_event.h"
     17
     18static bool vmci_disable_host;
     19module_param_named(disable_host, vmci_disable_host, bool, 0);
     20MODULE_PARM_DESC(disable_host,
     21		 "Disable driver host personality (default=enabled)");
     22
     23static bool vmci_disable_guest;
     24module_param_named(disable_guest, vmci_disable_guest, bool, 0);
     25MODULE_PARM_DESC(disable_guest,
     26		 "Disable driver guest personality (default=enabled)");
     27
     28static bool vmci_guest_personality_initialized;
     29static bool vmci_host_personality_initialized;
     30
     31static DEFINE_MUTEX(vmci_vsock_mutex); /* protects vmci_vsock_transport_cb */
     32static vmci_vsock_cb vmci_vsock_transport_cb;
     33static bool vmci_vsock_cb_host_called;
     34
     35/*
     36 * vmci_get_context_id() - Gets the current context ID.
     37 *
     38 * Returns the current context ID.  Note that since this is accessed only
     39 * from code running in the host, this always returns the host context ID.
     40 */
     41u32 vmci_get_context_id(void)
     42{
     43	if (vmci_guest_code_active())
     44		return vmci_get_vm_context_id();
     45	else if (vmci_host_code_active())
     46		return VMCI_HOST_CONTEXT_ID;
     47
     48	return VMCI_INVALID_ID;
     49}
     50EXPORT_SYMBOL_GPL(vmci_get_context_id);
     51
     52/*
     53 * vmci_register_vsock_callback() - Register the VSOCK vmci_transport callback.
     54 *
     55 * The callback will be called when the first host or guest becomes active,
     56 * or if they are already active when this function is called.
     57 * To unregister the callback, call this function with NULL parameter.
     58 *
     59 * Returns 0 on success. -EBUSY if a callback is already registered.
     60 */
     61int vmci_register_vsock_callback(vmci_vsock_cb callback)
     62{
     63	int err = 0;
     64
     65	mutex_lock(&vmci_vsock_mutex);
     66
     67	if (vmci_vsock_transport_cb && callback) {
     68		err = -EBUSY;
     69		goto out;
     70	}
     71
     72	vmci_vsock_transport_cb = callback;
     73
     74	if (!vmci_vsock_transport_cb) {
     75		vmci_vsock_cb_host_called = false;
     76		goto out;
     77	}
     78
     79	if (vmci_guest_code_active())
     80		vmci_vsock_transport_cb(false);
     81
     82	if (vmci_host_users() > 0) {
     83		vmci_vsock_cb_host_called = true;
     84		vmci_vsock_transport_cb(true);
     85	}
     86
     87out:
     88	mutex_unlock(&vmci_vsock_mutex);
     89	return err;
     90}
     91EXPORT_SYMBOL_GPL(vmci_register_vsock_callback);
     92
     93void vmci_call_vsock_callback(bool is_host)
     94{
     95	mutex_lock(&vmci_vsock_mutex);
     96
     97	if (!vmci_vsock_transport_cb)
     98		goto out;
     99
    100	/* In the host, this function could be called multiple times,
    101	 * but we want to register it only once.
    102	 */
    103	if (is_host) {
    104		if (vmci_vsock_cb_host_called)
    105			goto out;
    106
    107		vmci_vsock_cb_host_called = true;
    108	}
    109
    110	vmci_vsock_transport_cb(is_host);
    111out:
    112	mutex_unlock(&vmci_vsock_mutex);
    113}
    114
    115static int __init vmci_drv_init(void)
    116{
    117	int vmci_err;
    118	int error;
    119
    120	vmci_err = vmci_event_init();
    121	if (vmci_err < VMCI_SUCCESS) {
    122		pr_err("Failed to initialize VMCIEvent (result=%d)\n",
    123		       vmci_err);
    124		return -EINVAL;
    125	}
    126
    127	if (!vmci_disable_guest) {
    128		error = vmci_guest_init();
    129		if (error) {
    130			pr_warn("Failed to initialize guest personality (err=%d)\n",
    131				error);
    132		} else {
    133			vmci_guest_personality_initialized = true;
    134			pr_info("Guest personality initialized and is %s\n",
    135				vmci_guest_code_active() ?
    136				"active" : "inactive");
    137		}
    138	}
    139
    140	if (!vmci_disable_host) {
    141		error = vmci_host_init();
    142		if (error) {
    143			pr_warn("Unable to initialize host personality (err=%d)\n",
    144				error);
    145		} else {
    146			vmci_host_personality_initialized = true;
    147			pr_info("Initialized host personality\n");
    148		}
    149	}
    150
    151	if (!vmci_guest_personality_initialized &&
    152	    !vmci_host_personality_initialized) {
    153		vmci_event_exit();
    154		return -ENODEV;
    155	}
    156
    157	return 0;
    158}
    159module_init(vmci_drv_init);
    160
    161static void __exit vmci_drv_exit(void)
    162{
    163	if (vmci_guest_personality_initialized)
    164		vmci_guest_exit();
    165
    166	if (vmci_host_personality_initialized)
    167		vmci_host_exit();
    168
    169	vmci_event_exit();
    170}
    171module_exit(vmci_drv_exit);
    172
    173MODULE_AUTHOR("VMware, Inc.");
    174MODULE_DESCRIPTION("VMware Virtual Machine Communication Interface.");
    175MODULE_VERSION("1.1.6.0-k");
    176MODULE_LICENSE("GPL v2");