1197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang/*
2197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang * VMware VMCI Driver
3197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang *
4197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang * Copyright (C) 2012 VMware, Inc. All rights reserved.
5197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang *
6197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang * This program is free software; you can redistribute it and/or modify it
7197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang * under the terms of the GNU General Public License as published by the
8197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang * Free Software Foundation version 2 and no later version.
9197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang *
10197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang * This program is distributed in the hope that it will be useful, but
11197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang * for more details.
14197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang */
15197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang
16197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang#include <linux/vmw_vmci_defs.h>
17197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang#include <linux/vmw_vmci_api.h>
18197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang#include <linux/atomic.h>
19197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang#include <linux/kernel.h>
20197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang#include <linux/module.h>
21197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang#include <linux/init.h>
22197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang
23197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang#include "vmci_driver.h"
24197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang#include "vmci_event.h"
25197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang
26197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhangstatic bool vmci_disable_host;
27197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhangmodule_param_named(disable_host, vmci_disable_host, bool, 0);
28197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge ZhangMODULE_PARM_DESC(disable_host,
29197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang		 "Disable driver host personality (default=enabled)");
30197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang
31197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhangstatic bool vmci_disable_guest;
32197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhangmodule_param_named(disable_guest, vmci_disable_guest, bool, 0);
33197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge ZhangMODULE_PARM_DESC(disable_guest,
34197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang		 "Disable driver guest personality (default=enabled)");
35197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang
36197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhangstatic bool vmci_guest_personality_initialized;
37197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhangstatic bool vmci_host_personality_initialized;
38197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang
39197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang/*
40197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang * vmci_get_context_id() - Gets the current context ID.
41197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang *
42197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang * Returns the current context ID.  Note that since this is accessed only
43197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang * from code running in the host, this always returns the host context ID.
44197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang */
45197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhangu32 vmci_get_context_id(void)
46197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang{
47197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang	if (vmci_guest_code_active())
48197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang		return vmci_get_vm_context_id();
49197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang	else if (vmci_host_code_active())
50197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang		return VMCI_HOST_CONTEXT_ID;
51197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang
52197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang	return VMCI_INVALID_ID;
53197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang}
54197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge ZhangEXPORT_SYMBOL_GPL(vmci_get_context_id);
55197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang
56197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhangstatic int __init vmci_drv_init(void)
57197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang{
58197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang	int vmci_err;
59197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang	int error;
60197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang
61197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang	vmci_err = vmci_event_init();
62197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang	if (vmci_err < VMCI_SUCCESS) {
63197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang		pr_err("Failed to initialize VMCIEvent (result=%d)\n",
64197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang		       vmci_err);
65197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang		return -EINVAL;
66197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang	}
67197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang
68197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang	if (!vmci_disable_guest) {
69197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang		error = vmci_guest_init();
70197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang		if (error) {
71197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang			pr_warn("Failed to initialize guest personality (err=%d)\n",
72197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang				error);
73197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang		} else {
74197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang			vmci_guest_personality_initialized = true;
75197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang			pr_info("Guest personality initialized and is %s\n",
76197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang				vmci_guest_code_active() ?
77197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang				"active" : "inactive");
78197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang		}
79197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang	}
80197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang
81197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang	if (!vmci_disable_host) {
82197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang		error = vmci_host_init();
83197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang		if (error) {
84197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang			pr_warn("Unable to initialize host personality (err=%d)\n",
85197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang				error);
86197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang		} else {
87197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang			vmci_host_personality_initialized = true;
88197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang			pr_info("Initialized host personality\n");
89197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang		}
90197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang	}
91197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang
92197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang	if (!vmci_guest_personality_initialized &&
93197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang	    !vmci_host_personality_initialized) {
94197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang		vmci_event_exit();
95197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang		return -ENODEV;
96197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang	}
97197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang
98197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang	return 0;
99197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang}
100197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhangmodule_init(vmci_drv_init);
101197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang
102197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhangstatic void __exit vmci_drv_exit(void)
103197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang{
104197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang	if (vmci_guest_personality_initialized)
105197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang		vmci_guest_exit();
106197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang
107197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang	if (vmci_host_personality_initialized)
108197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang		vmci_host_exit();
109197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang
110197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang	vmci_event_exit();
111197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang}
112197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhangmodule_exit(vmci_drv_exit);
113197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge Zhang
114197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge ZhangMODULE_AUTHOR("VMware, Inc.");
115197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge ZhangMODULE_DESCRIPTION("VMware Virtual Machine Communication Interface.");
1166d6dfb4f4aa9ee352a199b5379942350bdd26e64Andy KingMODULE_VERSION("1.1.0.0-k");
117197dbaaabd51c170f9b77bd1c401d4ea0361bb7bGeorge ZhangMODULE_LICENSE("GPL v2");
118