0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/vmw_vmci_defs.h>
0009 #include <linux/vmw_vmci_api.h>
0010 #include <linux/atomic.h>
0011 #include <linux/kernel.h>
0012 #include <linux/module.h>
0013 #include <linux/init.h>
0014
0015 #include "vmci_driver.h"
0016 #include "vmci_event.h"
0017
0018 static bool vmci_disable_host;
0019 module_param_named(disable_host, vmci_disable_host, bool, 0);
0020 MODULE_PARM_DESC(disable_host,
0021 "Disable driver host personality (default=enabled)");
0022
0023 static bool vmci_disable_guest;
0024 module_param_named(disable_guest, vmci_disable_guest, bool, 0);
0025 MODULE_PARM_DESC(disable_guest,
0026 "Disable driver guest personality (default=enabled)");
0027
0028 static bool vmci_guest_personality_initialized;
0029 static bool vmci_host_personality_initialized;
0030
0031 static DEFINE_MUTEX(vmci_vsock_mutex);
0032 static vmci_vsock_cb vmci_vsock_transport_cb;
0033 static bool vmci_vsock_cb_host_called;
0034
0035
0036
0037
0038
0039
0040
0041 u32 vmci_get_context_id(void)
0042 {
0043 if (vmci_guest_code_active())
0044 return vmci_get_vm_context_id();
0045 else if (vmci_host_code_active())
0046 return VMCI_HOST_CONTEXT_ID;
0047
0048 return VMCI_INVALID_ID;
0049 }
0050 EXPORT_SYMBOL_GPL(vmci_get_context_id);
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061 int vmci_register_vsock_callback(vmci_vsock_cb callback)
0062 {
0063 int err = 0;
0064
0065 mutex_lock(&vmci_vsock_mutex);
0066
0067 if (vmci_vsock_transport_cb && callback) {
0068 err = -EBUSY;
0069 goto out;
0070 }
0071
0072 vmci_vsock_transport_cb = callback;
0073
0074 if (!vmci_vsock_transport_cb) {
0075 vmci_vsock_cb_host_called = false;
0076 goto out;
0077 }
0078
0079 if (vmci_guest_code_active())
0080 vmci_vsock_transport_cb(false);
0081
0082 if (vmci_host_users() > 0) {
0083 vmci_vsock_cb_host_called = true;
0084 vmci_vsock_transport_cb(true);
0085 }
0086
0087 out:
0088 mutex_unlock(&vmci_vsock_mutex);
0089 return err;
0090 }
0091 EXPORT_SYMBOL_GPL(vmci_register_vsock_callback);
0092
0093 void vmci_call_vsock_callback(bool is_host)
0094 {
0095 mutex_lock(&vmci_vsock_mutex);
0096
0097 if (!vmci_vsock_transport_cb)
0098 goto out;
0099
0100
0101
0102
0103 if (is_host) {
0104 if (vmci_vsock_cb_host_called)
0105 goto out;
0106
0107 vmci_vsock_cb_host_called = true;
0108 }
0109
0110 vmci_vsock_transport_cb(is_host);
0111 out:
0112 mutex_unlock(&vmci_vsock_mutex);
0113 }
0114
0115 static int __init vmci_drv_init(void)
0116 {
0117 int vmci_err;
0118 int error;
0119
0120 vmci_err = vmci_event_init();
0121 if (vmci_err < VMCI_SUCCESS) {
0122 pr_err("Failed to initialize VMCIEvent (result=%d)\n",
0123 vmci_err);
0124 return -EINVAL;
0125 }
0126
0127 if (!vmci_disable_guest) {
0128 error = vmci_guest_init();
0129 if (error) {
0130 pr_warn("Failed to initialize guest personality (err=%d)\n",
0131 error);
0132 } else {
0133 vmci_guest_personality_initialized = true;
0134 pr_info("Guest personality initialized and is %s\n",
0135 vmci_guest_code_active() ?
0136 "active" : "inactive");
0137 }
0138 }
0139
0140 if (!vmci_disable_host) {
0141 error = vmci_host_init();
0142 if (error) {
0143 pr_warn("Unable to initialize host personality (err=%d)\n",
0144 error);
0145 } else {
0146 vmci_host_personality_initialized = true;
0147 pr_info("Initialized host personality\n");
0148 }
0149 }
0150
0151 if (!vmci_guest_personality_initialized &&
0152 !vmci_host_personality_initialized) {
0153 vmci_event_exit();
0154 return -ENODEV;
0155 }
0156
0157 return 0;
0158 }
0159 module_init(vmci_drv_init);
0160
0161 static void __exit vmci_drv_exit(void)
0162 {
0163 if (vmci_guest_personality_initialized)
0164 vmci_guest_exit();
0165
0166 if (vmci_host_personality_initialized)
0167 vmci_host_exit();
0168
0169 vmci_event_exit();
0170 }
0171 module_exit(vmci_drv_exit);
0172
0173 MODULE_AUTHOR("VMware, Inc.");
0174 MODULE_DESCRIPTION("VMware Virtual Machine Communication Interface.");
0175 MODULE_VERSION("1.1.6.0-k");
0176 MODULE_LICENSE("GPL v2");