1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-only */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * VMware VMCI driver (vmciContext.h)
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2012 VMware, Inc. All rights reserved.
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #ifndef _VMCI_CONTEXT_H_
9*4882a593Smuzhiyun #define _VMCI_CONTEXT_H_
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include <linux/vmw_vmci_defs.h>
12*4882a593Smuzhiyun #include <linux/atomic.h>
13*4882a593Smuzhiyun #include <linux/kref.h>
14*4882a593Smuzhiyun #include <linux/types.h>
15*4882a593Smuzhiyun #include <linux/wait.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include "vmci_handle_array.h"
18*4882a593Smuzhiyun #include "vmci_datagram.h"
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun /* Used to determine what checkpoint state to get and set. */
21*4882a593Smuzhiyun enum {
22*4882a593Smuzhiyun VMCI_NOTIFICATION_CPT_STATE = 1,
23*4882a593Smuzhiyun VMCI_WELLKNOWN_CPT_STATE = 2,
24*4882a593Smuzhiyun VMCI_DG_OUT_STATE = 3,
25*4882a593Smuzhiyun VMCI_DG_IN_STATE = 4,
26*4882a593Smuzhiyun VMCI_DG_IN_SIZE_STATE = 5,
27*4882a593Smuzhiyun VMCI_DOORBELL_CPT_STATE = 6,
28*4882a593Smuzhiyun };
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun /* Host specific struct used for signalling */
31*4882a593Smuzhiyun struct vmci_host {
32*4882a593Smuzhiyun wait_queue_head_t wait_queue;
33*4882a593Smuzhiyun };
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun struct vmci_handle_list {
36*4882a593Smuzhiyun struct list_head node;
37*4882a593Smuzhiyun struct vmci_handle handle;
38*4882a593Smuzhiyun };
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun struct vmci_ctx {
41*4882a593Smuzhiyun struct list_head list_item; /* For global VMCI list. */
42*4882a593Smuzhiyun u32 cid;
43*4882a593Smuzhiyun struct kref kref;
44*4882a593Smuzhiyun struct list_head datagram_queue; /* Head of per VM queue. */
45*4882a593Smuzhiyun u32 pending_datagrams;
46*4882a593Smuzhiyun size_t datagram_queue_size; /* Size of datagram queue in bytes. */
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun /*
49*4882a593Smuzhiyun * Version of the code that created
50*4882a593Smuzhiyun * this context; e.g., VMX.
51*4882a593Smuzhiyun */
52*4882a593Smuzhiyun int user_version;
53*4882a593Smuzhiyun spinlock_t lock; /* Locks callQueue and handle_arrays. */
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun /*
56*4882a593Smuzhiyun * queue_pairs attached to. The array of
57*4882a593Smuzhiyun * handles for queue pairs is accessed
58*4882a593Smuzhiyun * from the code for QP API, and there
59*4882a593Smuzhiyun * it is protected by the QP lock. It
60*4882a593Smuzhiyun * is also accessed from the context
61*4882a593Smuzhiyun * clean up path, which does not
62*4882a593Smuzhiyun * require a lock. VMCILock is not
63*4882a593Smuzhiyun * used to protect the QP array field.
64*4882a593Smuzhiyun */
65*4882a593Smuzhiyun struct vmci_handle_arr *queue_pair_array;
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun /* Doorbells created by context. */
68*4882a593Smuzhiyun struct vmci_handle_arr *doorbell_array;
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun /* Doorbells pending for context. */
71*4882a593Smuzhiyun struct vmci_handle_arr *pending_doorbell_array;
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun /* Contexts current context is subscribing to. */
74*4882a593Smuzhiyun struct list_head notifier_list;
75*4882a593Smuzhiyun unsigned int n_notifiers;
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun struct vmci_host host_context;
78*4882a593Smuzhiyun u32 priv_flags;
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun const struct cred *cred;
81*4882a593Smuzhiyun bool *notify; /* Notify flag pointer - hosted only. */
82*4882a593Smuzhiyun struct page *notify_page; /* Page backing the notify UVA. */
83*4882a593Smuzhiyun };
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun /* VMCINotifyAddRemoveInfo: Used to add/remove remote context notifications. */
86*4882a593Smuzhiyun struct vmci_ctx_info {
87*4882a593Smuzhiyun u32 remote_cid;
88*4882a593Smuzhiyun int result;
89*4882a593Smuzhiyun };
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun /* VMCICptBufInfo: Used to set/get current context's checkpoint state. */
92*4882a593Smuzhiyun struct vmci_ctx_chkpt_buf_info {
93*4882a593Smuzhiyun u64 cpt_buf;
94*4882a593Smuzhiyun u32 cpt_type;
95*4882a593Smuzhiyun u32 buf_size;
96*4882a593Smuzhiyun s32 result;
97*4882a593Smuzhiyun u32 _pad;
98*4882a593Smuzhiyun };
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun /*
101*4882a593Smuzhiyun * VMCINotificationReceiveInfo: Used to recieve pending notifications
102*4882a593Smuzhiyun * for doorbells and queue pairs.
103*4882a593Smuzhiyun */
104*4882a593Smuzhiyun struct vmci_ctx_notify_recv_info {
105*4882a593Smuzhiyun u64 db_handle_buf_uva;
106*4882a593Smuzhiyun u64 db_handle_buf_size;
107*4882a593Smuzhiyun u64 qp_handle_buf_uva;
108*4882a593Smuzhiyun u64 qp_handle_buf_size;
109*4882a593Smuzhiyun s32 result;
110*4882a593Smuzhiyun u32 _pad;
111*4882a593Smuzhiyun };
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun /*
114*4882a593Smuzhiyun * Utilility function that checks whether two entities are allowed
115*4882a593Smuzhiyun * to interact. If one of them is restricted, the other one must
116*4882a593Smuzhiyun * be trusted.
117*4882a593Smuzhiyun */
vmci_deny_interaction(u32 part_one,u32 part_two)118*4882a593Smuzhiyun static inline bool vmci_deny_interaction(u32 part_one, u32 part_two)
119*4882a593Smuzhiyun {
120*4882a593Smuzhiyun return ((part_one & VMCI_PRIVILEGE_FLAG_RESTRICTED) &&
121*4882a593Smuzhiyun !(part_two & VMCI_PRIVILEGE_FLAG_TRUSTED)) ||
122*4882a593Smuzhiyun ((part_two & VMCI_PRIVILEGE_FLAG_RESTRICTED) &&
123*4882a593Smuzhiyun !(part_one & VMCI_PRIVILEGE_FLAG_TRUSTED));
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun struct vmci_ctx *vmci_ctx_create(u32 cid, u32 flags,
127*4882a593Smuzhiyun uintptr_t event_hnd, int version,
128*4882a593Smuzhiyun const struct cred *cred);
129*4882a593Smuzhiyun void vmci_ctx_destroy(struct vmci_ctx *context);
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun bool vmci_ctx_supports_host_qp(struct vmci_ctx *context);
132*4882a593Smuzhiyun int vmci_ctx_enqueue_datagram(u32 cid, struct vmci_datagram *dg);
133*4882a593Smuzhiyun int vmci_ctx_dequeue_datagram(struct vmci_ctx *context,
134*4882a593Smuzhiyun size_t *max_size, struct vmci_datagram **dg);
135*4882a593Smuzhiyun int vmci_ctx_pending_datagrams(u32 cid, u32 *pending);
136*4882a593Smuzhiyun struct vmci_ctx *vmci_ctx_get(u32 cid);
137*4882a593Smuzhiyun void vmci_ctx_put(struct vmci_ctx *context);
138*4882a593Smuzhiyun bool vmci_ctx_exists(u32 cid);
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun int vmci_ctx_add_notification(u32 context_id, u32 remote_cid);
141*4882a593Smuzhiyun int vmci_ctx_remove_notification(u32 context_id, u32 remote_cid);
142*4882a593Smuzhiyun int vmci_ctx_get_chkpt_state(u32 context_id, u32 cpt_type,
143*4882a593Smuzhiyun u32 *num_cids, void **cpt_buf_ptr);
144*4882a593Smuzhiyun int vmci_ctx_set_chkpt_state(u32 context_id, u32 cpt_type,
145*4882a593Smuzhiyun u32 num_cids, void *cpt_buf);
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun int vmci_ctx_qp_create(struct vmci_ctx *context, struct vmci_handle handle);
148*4882a593Smuzhiyun int vmci_ctx_qp_destroy(struct vmci_ctx *context, struct vmci_handle handle);
149*4882a593Smuzhiyun bool vmci_ctx_qp_exists(struct vmci_ctx *context, struct vmci_handle handle);
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun void vmci_ctx_check_signal_notify(struct vmci_ctx *context);
152*4882a593Smuzhiyun void vmci_ctx_unset_notify(struct vmci_ctx *context);
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun int vmci_ctx_dbell_create(u32 context_id, struct vmci_handle handle);
155*4882a593Smuzhiyun int vmci_ctx_dbell_destroy(u32 context_id, struct vmci_handle handle);
156*4882a593Smuzhiyun int vmci_ctx_dbell_destroy_all(u32 context_id);
157*4882a593Smuzhiyun int vmci_ctx_notify_dbell(u32 cid, struct vmci_handle handle,
158*4882a593Smuzhiyun u32 src_priv_flags);
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun int vmci_ctx_rcv_notifications_get(u32 context_id, struct vmci_handle_arr
161*4882a593Smuzhiyun **db_handle_array, struct vmci_handle_arr
162*4882a593Smuzhiyun **qp_handle_array);
163*4882a593Smuzhiyun void vmci_ctx_rcv_notifications_release(u32 context_id, struct vmci_handle_arr
164*4882a593Smuzhiyun *db_handle_array, struct vmci_handle_arr
165*4882a593Smuzhiyun *qp_handle_array, bool success);
166*4882a593Smuzhiyun
vmci_ctx_get_id(struct vmci_ctx * context)167*4882a593Smuzhiyun static inline u32 vmci_ctx_get_id(struct vmci_ctx *context)
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun if (!context)
170*4882a593Smuzhiyun return VMCI_INVALID_ID;
171*4882a593Smuzhiyun return context->cid;
172*4882a593Smuzhiyun }
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun #endif /* _VMCI_CONTEXT_H_ */
175