Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * VMware VMCI Driver
0004  *
0005  * Copyright (C) 2012 VMware, Inc. All rights reserved.
0006  */
0007 
0008 #include <linux/vmw_vmci_defs.h>
0009 #include <linux/vmw_vmci_api.h>
0010 #include <linux/highmem.h>
0011 #include <linux/kernel.h>
0012 #include <linux/module.h>
0013 #include <linux/sched.h>
0014 #include <linux/cred.h>
0015 #include <linux/slab.h>
0016 
0017 #include "vmci_queue_pair.h"
0018 #include "vmci_datagram.h"
0019 #include "vmci_doorbell.h"
0020 #include "vmci_context.h"
0021 #include "vmci_driver.h"
0022 #include "vmci_event.h"
0023 
0024 /* Use a wide upper bound for the maximum contexts. */
0025 #define VMCI_MAX_CONTEXTS 2000
0026 
0027 /*
0028  * List of current VMCI contexts.  Contexts can be added by
0029  * vmci_ctx_create() and removed via vmci_ctx_destroy().
0030  * These, along with context lookup, are protected by the
0031  * list structure's lock.
0032  */
0033 static struct {
0034     struct list_head head;
0035     spinlock_t lock; /* Spinlock for context list operations */
0036 } ctx_list = {
0037     .head = LIST_HEAD_INIT(ctx_list.head),
0038     .lock = __SPIN_LOCK_UNLOCKED(ctx_list.lock),
0039 };
0040 
0041 /* Used by contexts that did not set up notify flag pointers */
0042 static bool ctx_dummy_notify;
0043 
0044 static void ctx_signal_notify(struct vmci_ctx *context)
0045 {
0046     *context->notify = true;
0047 }
0048 
0049 static void ctx_clear_notify(struct vmci_ctx *context)
0050 {
0051     *context->notify = false;
0052 }
0053 
0054 /*
0055  * If nothing requires the attention of the guest, clears both
0056  * notify flag and call.
0057  */
0058 static void ctx_clear_notify_call(struct vmci_ctx *context)
0059 {
0060     if (context->pending_datagrams == 0 &&
0061         vmci_handle_arr_get_size(context->pending_doorbell_array) == 0)
0062         ctx_clear_notify(context);
0063 }
0064 
0065 /*
0066  * Sets the context's notify flag iff datagrams are pending for this
0067  * context.  Called from vmci_setup_notify().
0068  */
0069 void vmci_ctx_check_signal_notify(struct vmci_ctx *context)
0070 {
0071     spin_lock(&context->lock);
0072     if (context->pending_datagrams)
0073         ctx_signal_notify(context);
0074     spin_unlock(&context->lock);
0075 }
0076 
0077 /*
0078  * Allocates and initializes a VMCI context.
0079  */
0080 struct vmci_ctx *vmci_ctx_create(u32 cid, u32 priv_flags,
0081                  uintptr_t event_hnd,
0082                  int user_version,
0083                  const struct cred *cred)
0084 {
0085     struct vmci_ctx *context;
0086     int error;
0087 
0088     if (cid == VMCI_INVALID_ID) {
0089         pr_devel("Invalid context ID for VMCI context\n");
0090         error = -EINVAL;
0091         goto err_out;
0092     }
0093 
0094     if (priv_flags & ~VMCI_PRIVILEGE_ALL_FLAGS) {
0095         pr_devel("Invalid flag (flags=0x%x) for VMCI context\n",
0096              priv_flags);
0097         error = -EINVAL;
0098         goto err_out;
0099     }
0100 
0101     if (user_version == 0) {
0102         pr_devel("Invalid suer_version %d\n", user_version);
0103         error = -EINVAL;
0104         goto err_out;
0105     }
0106 
0107     context = kzalloc(sizeof(*context), GFP_KERNEL);
0108     if (!context) {
0109         pr_warn("Failed to allocate memory for VMCI context\n");
0110         error = -ENOMEM;
0111         goto err_out;
0112     }
0113 
0114     kref_init(&context->kref);
0115     spin_lock_init(&context->lock);
0116     INIT_LIST_HEAD(&context->list_item);
0117     INIT_LIST_HEAD(&context->datagram_queue);
0118     INIT_LIST_HEAD(&context->notifier_list);
0119 
0120     /* Initialize host-specific VMCI context. */
0121     init_waitqueue_head(&context->host_context.wait_queue);
0122 
0123     context->queue_pair_array =
0124         vmci_handle_arr_create(0, VMCI_MAX_GUEST_QP_COUNT);
0125     if (!context->queue_pair_array) {
0126         error = -ENOMEM;
0127         goto err_free_ctx;
0128     }
0129 
0130     context->doorbell_array =
0131         vmci_handle_arr_create(0, VMCI_MAX_GUEST_DOORBELL_COUNT);
0132     if (!context->doorbell_array) {
0133         error = -ENOMEM;
0134         goto err_free_qp_array;
0135     }
0136 
0137     context->pending_doorbell_array =
0138         vmci_handle_arr_create(0, VMCI_MAX_GUEST_DOORBELL_COUNT);
0139     if (!context->pending_doorbell_array) {
0140         error = -ENOMEM;
0141         goto err_free_db_array;
0142     }
0143 
0144     context->user_version = user_version;
0145 
0146     context->priv_flags = priv_flags;
0147 
0148     if (cred)
0149         context->cred = get_cred(cred);
0150 
0151     context->notify = &ctx_dummy_notify;
0152     context->notify_page = NULL;
0153 
0154     /*
0155      * If we collide with an existing context we generate a new
0156      * and use it instead. The VMX will determine if regeneration
0157      * is okay. Since there isn't 4B - 16 VMs running on a given
0158      * host, the below loop will terminate.
0159      */
0160     spin_lock(&ctx_list.lock);
0161 
0162     while (vmci_ctx_exists(cid)) {
0163         /* We reserve the lowest 16 ids for fixed contexts. */
0164         cid = max(cid, VMCI_RESERVED_CID_LIMIT - 1) + 1;
0165         if (cid == VMCI_INVALID_ID)
0166             cid = VMCI_RESERVED_CID_LIMIT;
0167     }
0168     context->cid = cid;
0169 
0170     list_add_tail_rcu(&context->list_item, &ctx_list.head);
0171     spin_unlock(&ctx_list.lock);
0172 
0173     return context;
0174 
0175  err_free_db_array:
0176     vmci_handle_arr_destroy(context->doorbell_array);
0177  err_free_qp_array:
0178     vmci_handle_arr_destroy(context->queue_pair_array);
0179  err_free_ctx:
0180     kfree(context);
0181  err_out:
0182     return ERR_PTR(error);
0183 }
0184 
0185 /*
0186  * Destroy VMCI context.
0187  */
0188 void vmci_ctx_destroy(struct vmci_ctx *context)
0189 {
0190     spin_lock(&ctx_list.lock);
0191     list_del_rcu(&context->list_item);
0192     spin_unlock(&ctx_list.lock);
0193     synchronize_rcu();
0194 
0195     vmci_ctx_put(context);
0196 }
0197 
0198 /*
0199  * Fire notification for all contexts interested in given cid.
0200  */
0201 static int ctx_fire_notification(u32 context_id, u32 priv_flags)
0202 {
0203     u32 i, array_size;
0204     struct vmci_ctx *sub_ctx;
0205     struct vmci_handle_arr *subscriber_array;
0206     struct vmci_handle context_handle =
0207         vmci_make_handle(context_id, VMCI_EVENT_HANDLER);
0208 
0209     /*
0210      * We create an array to hold the subscribers we find when
0211      * scanning through all contexts.
0212      */
0213     subscriber_array = vmci_handle_arr_create(0, VMCI_MAX_CONTEXTS);
0214     if (subscriber_array == NULL)
0215         return VMCI_ERROR_NO_MEM;
0216 
0217     /*
0218      * Scan all contexts to find who is interested in being
0219      * notified about given contextID.
0220      */
0221     rcu_read_lock();
0222     list_for_each_entry_rcu(sub_ctx, &ctx_list.head, list_item) {
0223         struct vmci_handle_list *node;
0224 
0225         /*
0226          * We only deliver notifications of the removal of
0227          * contexts, if the two contexts are allowed to
0228          * interact.
0229          */
0230         if (vmci_deny_interaction(priv_flags, sub_ctx->priv_flags))
0231             continue;
0232 
0233         list_for_each_entry_rcu(node, &sub_ctx->notifier_list, node) {
0234             if (!vmci_handle_is_equal(node->handle, context_handle))
0235                 continue;
0236 
0237             vmci_handle_arr_append_entry(&subscriber_array,
0238                     vmci_make_handle(sub_ctx->cid,
0239                              VMCI_EVENT_HANDLER));
0240         }
0241     }
0242     rcu_read_unlock();
0243 
0244     /* Fire event to all subscribers. */
0245     array_size = vmci_handle_arr_get_size(subscriber_array);
0246     for (i = 0; i < array_size; i++) {
0247         int result;
0248         struct vmci_event_ctx ev;
0249 
0250         ev.msg.hdr.dst = vmci_handle_arr_get_entry(subscriber_array, i);
0251         ev.msg.hdr.src = vmci_make_handle(VMCI_HYPERVISOR_CONTEXT_ID,
0252                           VMCI_CONTEXT_RESOURCE_ID);
0253         ev.msg.hdr.payload_size = sizeof(ev) - sizeof(ev.msg.hdr);
0254         ev.msg.event_data.event = VMCI_EVENT_CTX_REMOVED;
0255         ev.payload.context_id = context_id;
0256 
0257         result = vmci_datagram_dispatch(VMCI_HYPERVISOR_CONTEXT_ID,
0258                         &ev.msg.hdr, false);
0259         if (result < VMCI_SUCCESS) {
0260             pr_devel("Failed to enqueue event datagram (type=%d) for context (ID=0x%x)\n",
0261                  ev.msg.event_data.event,
0262                  ev.msg.hdr.dst.context);
0263             /* We continue to enqueue on next subscriber. */
0264         }
0265     }
0266     vmci_handle_arr_destroy(subscriber_array);
0267 
0268     return VMCI_SUCCESS;
0269 }
0270 
0271 /*
0272  * Returns the current number of pending datagrams. The call may
0273  * also serve as a synchronization point for the datagram queue,
0274  * as no enqueue operations can occur concurrently.
0275  */
0276 int vmci_ctx_pending_datagrams(u32 cid, u32 *pending)
0277 {
0278     struct vmci_ctx *context;
0279 
0280     context = vmci_ctx_get(cid);
0281     if (context == NULL)
0282         return VMCI_ERROR_INVALID_ARGS;
0283 
0284     spin_lock(&context->lock);
0285     if (pending)
0286         *pending = context->pending_datagrams;
0287     spin_unlock(&context->lock);
0288     vmci_ctx_put(context);
0289 
0290     return VMCI_SUCCESS;
0291 }
0292 
0293 /*
0294  * Queues a VMCI datagram for the appropriate target VM context.
0295  */
0296 int vmci_ctx_enqueue_datagram(u32 cid, struct vmci_datagram *dg)
0297 {
0298     struct vmci_datagram_queue_entry *dq_entry;
0299     struct vmci_ctx *context;
0300     struct vmci_handle dg_src;
0301     size_t vmci_dg_size;
0302 
0303     vmci_dg_size = VMCI_DG_SIZE(dg);
0304     if (vmci_dg_size > VMCI_MAX_DG_SIZE) {
0305         pr_devel("Datagram too large (bytes=%zu)\n", vmci_dg_size);
0306         return VMCI_ERROR_INVALID_ARGS;
0307     }
0308 
0309     /* Get the target VM's VMCI context. */
0310     context = vmci_ctx_get(cid);
0311     if (!context) {
0312         pr_devel("Invalid context (ID=0x%x)\n", cid);
0313         return VMCI_ERROR_INVALID_ARGS;
0314     }
0315 
0316     /* Allocate guest call entry and add it to the target VM's queue. */
0317     dq_entry = kmalloc(sizeof(*dq_entry), GFP_KERNEL);
0318     if (dq_entry == NULL) {
0319         pr_warn("Failed to allocate memory for datagram\n");
0320         vmci_ctx_put(context);
0321         return VMCI_ERROR_NO_MEM;
0322     }
0323     dq_entry->dg = dg;
0324     dq_entry->dg_size = vmci_dg_size;
0325     dg_src = dg->src;
0326     INIT_LIST_HEAD(&dq_entry->list_item);
0327 
0328     spin_lock(&context->lock);
0329 
0330     /*
0331      * We put a higher limit on datagrams from the hypervisor.  If
0332      * the pending datagram is not from hypervisor, then we check
0333      * if enqueueing it would exceed the
0334      * VMCI_MAX_DATAGRAM_QUEUE_SIZE limit on the destination.  If
0335      * the pending datagram is from hypervisor, we allow it to be
0336      * queued at the destination side provided we don't reach the
0337      * VMCI_MAX_DATAGRAM_AND_EVENT_QUEUE_SIZE limit.
0338      */
0339     if (context->datagram_queue_size + vmci_dg_size >=
0340         VMCI_MAX_DATAGRAM_QUEUE_SIZE &&
0341         (!vmci_handle_is_equal(dg_src,
0342                 vmci_make_handle
0343                 (VMCI_HYPERVISOR_CONTEXT_ID,
0344                  VMCI_CONTEXT_RESOURCE_ID)) ||
0345          context->datagram_queue_size + vmci_dg_size >=
0346          VMCI_MAX_DATAGRAM_AND_EVENT_QUEUE_SIZE)) {
0347         spin_unlock(&context->lock);
0348         vmci_ctx_put(context);
0349         kfree(dq_entry);
0350         pr_devel("Context (ID=0x%x) receive queue is full\n", cid);
0351         return VMCI_ERROR_NO_RESOURCES;
0352     }
0353 
0354     list_add(&dq_entry->list_item, &context->datagram_queue);
0355     context->pending_datagrams++;
0356     context->datagram_queue_size += vmci_dg_size;
0357     ctx_signal_notify(context);
0358     wake_up(&context->host_context.wait_queue);
0359     spin_unlock(&context->lock);
0360     vmci_ctx_put(context);
0361 
0362     return vmci_dg_size;
0363 }
0364 
0365 /*
0366  * Verifies whether a context with the specified context ID exists.
0367  * FIXME: utility is dubious as no decisions can be reliably made
0368  * using this data as context can appear and disappear at any time.
0369  */
0370 bool vmci_ctx_exists(u32 cid)
0371 {
0372     struct vmci_ctx *context;
0373     bool exists = false;
0374 
0375     rcu_read_lock();
0376 
0377     list_for_each_entry_rcu(context, &ctx_list.head, list_item) {
0378         if (context->cid == cid) {
0379             exists = true;
0380             break;
0381         }
0382     }
0383 
0384     rcu_read_unlock();
0385     return exists;
0386 }
0387 
0388 /*
0389  * Retrieves VMCI context corresponding to the given cid.
0390  */
0391 struct vmci_ctx *vmci_ctx_get(u32 cid)
0392 {
0393     struct vmci_ctx *c, *context = NULL;
0394 
0395     if (cid == VMCI_INVALID_ID)
0396         return NULL;
0397 
0398     rcu_read_lock();
0399     list_for_each_entry_rcu(c, &ctx_list.head, list_item) {
0400         if (c->cid == cid) {
0401             /*
0402              * The context owner drops its own reference to the
0403              * context only after removing it from the list and
0404              * waiting for RCU grace period to expire. This
0405              * means that we are not about to increase the
0406              * reference count of something that is in the
0407              * process of being destroyed.
0408              */
0409             context = c;
0410             kref_get(&context->kref);
0411             break;
0412         }
0413     }
0414     rcu_read_unlock();
0415 
0416     return context;
0417 }
0418 
0419 /*
0420  * Deallocates all parts of a context data structure. This
0421  * function doesn't lock the context, because it assumes that
0422  * the caller was holding the last reference to context.
0423  */
0424 static void ctx_free_ctx(struct kref *kref)
0425 {
0426     struct vmci_ctx *context = container_of(kref, struct vmci_ctx, kref);
0427     struct vmci_datagram_queue_entry *dq_entry, *dq_entry_tmp;
0428     struct vmci_handle temp_handle;
0429     struct vmci_handle_list *notifier, *tmp;
0430 
0431     /*
0432      * Fire event to all contexts interested in knowing this
0433      * context is dying.
0434      */
0435     ctx_fire_notification(context->cid, context->priv_flags);
0436 
0437     /*
0438      * Cleanup all queue pair resources attached to context.  If
0439      * the VM dies without cleaning up, this code will make sure
0440      * that no resources are leaked.
0441      */
0442     temp_handle = vmci_handle_arr_get_entry(context->queue_pair_array, 0);
0443     while (!vmci_handle_is_equal(temp_handle, VMCI_INVALID_HANDLE)) {
0444         if (vmci_qp_broker_detach(temp_handle,
0445                       context) < VMCI_SUCCESS) {
0446             /*
0447              * When vmci_qp_broker_detach() succeeds it
0448              * removes the handle from the array.  If
0449              * detach fails, we must remove the handle
0450              * ourselves.
0451              */
0452             vmci_handle_arr_remove_entry(context->queue_pair_array,
0453                              temp_handle);
0454         }
0455         temp_handle =
0456             vmci_handle_arr_get_entry(context->queue_pair_array, 0);
0457     }
0458 
0459     /*
0460      * It is fine to destroy this without locking the callQueue, as
0461      * this is the only thread having a reference to the context.
0462      */
0463     list_for_each_entry_safe(dq_entry, dq_entry_tmp,
0464                  &context->datagram_queue, list_item) {
0465         WARN_ON(dq_entry->dg_size != VMCI_DG_SIZE(dq_entry->dg));
0466         list_del(&dq_entry->list_item);
0467         kfree(dq_entry->dg);
0468         kfree(dq_entry);
0469     }
0470 
0471     list_for_each_entry_safe(notifier, tmp,
0472                  &context->notifier_list, node) {
0473         list_del(&notifier->node);
0474         kfree(notifier);
0475     }
0476 
0477     vmci_handle_arr_destroy(context->queue_pair_array);
0478     vmci_handle_arr_destroy(context->doorbell_array);
0479     vmci_handle_arr_destroy(context->pending_doorbell_array);
0480     vmci_ctx_unset_notify(context);
0481     if (context->cred)
0482         put_cred(context->cred);
0483     kfree(context);
0484 }
0485 
0486 /*
0487  * Drops reference to VMCI context. If this is the last reference to
0488  * the context it will be deallocated. A context is created with
0489  * a reference count of one, and on destroy, it is removed from
0490  * the context list before its reference count is decremented. Thus,
0491  * if we reach zero, we are sure that nobody else are about to increment
0492  * it (they need the entry in the context list for that), and so there
0493  * is no need for locking.
0494  */
0495 void vmci_ctx_put(struct vmci_ctx *context)
0496 {
0497     kref_put(&context->kref, ctx_free_ctx);
0498 }
0499 
0500 /*
0501  * Dequeues the next datagram and returns it to caller.
0502  * The caller passes in a pointer to the max size datagram
0503  * it can handle and the datagram is only unqueued if the
0504  * size is less than max_size. If larger max_size is set to
0505  * the size of the datagram to give the caller a chance to
0506  * set up a larger buffer for the guestcall.
0507  */
0508 int vmci_ctx_dequeue_datagram(struct vmci_ctx *context,
0509                   size_t *max_size,
0510                   struct vmci_datagram **dg)
0511 {
0512     struct vmci_datagram_queue_entry *dq_entry;
0513     struct list_head *list_item;
0514     int rv;
0515 
0516     /* Dequeue the next datagram entry. */
0517     spin_lock(&context->lock);
0518     if (context->pending_datagrams == 0) {
0519         ctx_clear_notify_call(context);
0520         spin_unlock(&context->lock);
0521         pr_devel("No datagrams pending\n");
0522         return VMCI_ERROR_NO_MORE_DATAGRAMS;
0523     }
0524 
0525     list_item = context->datagram_queue.next;
0526 
0527     dq_entry =
0528         list_entry(list_item, struct vmci_datagram_queue_entry, list_item);
0529 
0530     /* Check size of caller's buffer. */
0531     if (*max_size < dq_entry->dg_size) {
0532         *max_size = dq_entry->dg_size;
0533         spin_unlock(&context->lock);
0534         pr_devel("Caller's buffer should be at least (size=%u bytes)\n",
0535              (u32) *max_size);
0536         return VMCI_ERROR_NO_MEM;
0537     }
0538 
0539     list_del(list_item);
0540     context->pending_datagrams--;
0541     context->datagram_queue_size -= dq_entry->dg_size;
0542     if (context->pending_datagrams == 0) {
0543         ctx_clear_notify_call(context);
0544         rv = VMCI_SUCCESS;
0545     } else {
0546         /*
0547          * Return the size of the next datagram.
0548          */
0549         struct vmci_datagram_queue_entry *next_entry;
0550 
0551         list_item = context->datagram_queue.next;
0552         next_entry =
0553             list_entry(list_item, struct vmci_datagram_queue_entry,
0554                    list_item);
0555 
0556         /*
0557          * The following size_t -> int truncation is fine as
0558          * the maximum size of a (routable) datagram is 68KB.
0559          */
0560         rv = (int)next_entry->dg_size;
0561     }
0562     spin_unlock(&context->lock);
0563 
0564     /* Caller must free datagram. */
0565     *dg = dq_entry->dg;
0566     dq_entry->dg = NULL;
0567     kfree(dq_entry);
0568 
0569     return rv;
0570 }
0571 
0572 /*
0573  * Reverts actions set up by vmci_setup_notify().  Unmaps and unlocks the
0574  * page mapped/locked by vmci_setup_notify().
0575  */
0576 void vmci_ctx_unset_notify(struct vmci_ctx *context)
0577 {
0578     struct page *notify_page;
0579 
0580     spin_lock(&context->lock);
0581 
0582     notify_page = context->notify_page;
0583     context->notify = &ctx_dummy_notify;
0584     context->notify_page = NULL;
0585 
0586     spin_unlock(&context->lock);
0587 
0588     if (notify_page) {
0589         kunmap(notify_page);
0590         put_page(notify_page);
0591     }
0592 }
0593 
0594 /*
0595  * Add remote_cid to list of contexts current contexts wants
0596  * notifications from/about.
0597  */
0598 int vmci_ctx_add_notification(u32 context_id, u32 remote_cid)
0599 {
0600     struct vmci_ctx *context;
0601     struct vmci_handle_list *notifier, *n;
0602     int result;
0603     bool exists = false;
0604 
0605     context = vmci_ctx_get(context_id);
0606     if (!context)
0607         return VMCI_ERROR_NOT_FOUND;
0608 
0609     if (VMCI_CONTEXT_IS_VM(context_id) && VMCI_CONTEXT_IS_VM(remote_cid)) {
0610         pr_devel("Context removed notifications for other VMs not supported (src=0x%x, remote=0x%x)\n",
0611              context_id, remote_cid);
0612         result = VMCI_ERROR_DST_UNREACHABLE;
0613         goto out;
0614     }
0615 
0616     if (context->priv_flags & VMCI_PRIVILEGE_FLAG_RESTRICTED) {
0617         result = VMCI_ERROR_NO_ACCESS;
0618         goto out;
0619     }
0620 
0621     notifier = kmalloc(sizeof(struct vmci_handle_list), GFP_KERNEL);
0622     if (!notifier) {
0623         result = VMCI_ERROR_NO_MEM;
0624         goto out;
0625     }
0626 
0627     INIT_LIST_HEAD(&notifier->node);
0628     notifier->handle = vmci_make_handle(remote_cid, VMCI_EVENT_HANDLER);
0629 
0630     spin_lock(&context->lock);
0631 
0632     if (context->n_notifiers < VMCI_MAX_CONTEXTS) {
0633         list_for_each_entry(n, &context->notifier_list, node) {
0634             if (vmci_handle_is_equal(n->handle, notifier->handle)) {
0635                 exists = true;
0636                 break;
0637             }
0638         }
0639 
0640         if (exists) {
0641             kfree(notifier);
0642             result = VMCI_ERROR_ALREADY_EXISTS;
0643         } else {
0644             list_add_tail_rcu(&notifier->node,
0645                       &context->notifier_list);
0646             context->n_notifiers++;
0647             result = VMCI_SUCCESS;
0648         }
0649     } else {
0650         kfree(notifier);
0651         result = VMCI_ERROR_NO_MEM;
0652     }
0653 
0654     spin_unlock(&context->lock);
0655 
0656  out:
0657     vmci_ctx_put(context);
0658     return result;
0659 }
0660 
0661 /*
0662  * Remove remote_cid from current context's list of contexts it is
0663  * interested in getting notifications from/about.
0664  */
0665 int vmci_ctx_remove_notification(u32 context_id, u32 remote_cid)
0666 {
0667     struct vmci_ctx *context;
0668     struct vmci_handle_list *notifier = NULL, *iter, *tmp;
0669     struct vmci_handle handle;
0670 
0671     context = vmci_ctx_get(context_id);
0672     if (!context)
0673         return VMCI_ERROR_NOT_FOUND;
0674 
0675     handle = vmci_make_handle(remote_cid, VMCI_EVENT_HANDLER);
0676 
0677     spin_lock(&context->lock);
0678     list_for_each_entry_safe(iter, tmp,
0679                  &context->notifier_list, node) {
0680         if (vmci_handle_is_equal(iter->handle, handle)) {
0681             list_del_rcu(&iter->node);
0682             context->n_notifiers--;
0683             notifier = iter;
0684             break;
0685         }
0686     }
0687     spin_unlock(&context->lock);
0688 
0689     if (notifier)
0690         kvfree_rcu(notifier);
0691 
0692     vmci_ctx_put(context);
0693 
0694     return notifier ? VMCI_SUCCESS : VMCI_ERROR_NOT_FOUND;
0695 }
0696 
0697 static int vmci_ctx_get_chkpt_notifiers(struct vmci_ctx *context,
0698                     u32 *buf_size, void **pbuf)
0699 {
0700     u32 *notifiers;
0701     size_t data_size;
0702     struct vmci_handle_list *entry;
0703     int i = 0;
0704 
0705     if (context->n_notifiers == 0) {
0706         *buf_size = 0;
0707         *pbuf = NULL;
0708         return VMCI_SUCCESS;
0709     }
0710 
0711     data_size = context->n_notifiers * sizeof(*notifiers);
0712     if (*buf_size < data_size) {
0713         *buf_size = data_size;
0714         return VMCI_ERROR_MORE_DATA;
0715     }
0716 
0717     notifiers = kmalloc(data_size, GFP_ATOMIC); /* FIXME: want GFP_KERNEL */
0718     if (!notifiers)
0719         return VMCI_ERROR_NO_MEM;
0720 
0721     list_for_each_entry(entry, &context->notifier_list, node)
0722         notifiers[i++] = entry->handle.context;
0723 
0724     *buf_size = data_size;
0725     *pbuf = notifiers;
0726     return VMCI_SUCCESS;
0727 }
0728 
0729 static int vmci_ctx_get_chkpt_doorbells(struct vmci_ctx *context,
0730                     u32 *buf_size, void **pbuf)
0731 {
0732     struct dbell_cpt_state *dbells;
0733     u32 i, n_doorbells;
0734 
0735     n_doorbells = vmci_handle_arr_get_size(context->doorbell_array);
0736     if (n_doorbells > 0) {
0737         size_t data_size = n_doorbells * sizeof(*dbells);
0738         if (*buf_size < data_size) {
0739             *buf_size = data_size;
0740             return VMCI_ERROR_MORE_DATA;
0741         }
0742 
0743         dbells = kzalloc(data_size, GFP_ATOMIC);
0744         if (!dbells)
0745             return VMCI_ERROR_NO_MEM;
0746 
0747         for (i = 0; i < n_doorbells; i++)
0748             dbells[i].handle = vmci_handle_arr_get_entry(
0749                         context->doorbell_array, i);
0750 
0751         *buf_size = data_size;
0752         *pbuf = dbells;
0753     } else {
0754         *buf_size = 0;
0755         *pbuf = NULL;
0756     }
0757 
0758     return VMCI_SUCCESS;
0759 }
0760 
0761 /*
0762  * Get current context's checkpoint state of given type.
0763  */
0764 int vmci_ctx_get_chkpt_state(u32 context_id,
0765                  u32 cpt_type,
0766                  u32 *buf_size,
0767                  void **pbuf)
0768 {
0769     struct vmci_ctx *context;
0770     int result;
0771 
0772     context = vmci_ctx_get(context_id);
0773     if (!context)
0774         return VMCI_ERROR_NOT_FOUND;
0775 
0776     spin_lock(&context->lock);
0777 
0778     switch (cpt_type) {
0779     case VMCI_NOTIFICATION_CPT_STATE:
0780         result = vmci_ctx_get_chkpt_notifiers(context, buf_size, pbuf);
0781         break;
0782 
0783     case VMCI_WELLKNOWN_CPT_STATE:
0784         /*
0785          * For compatibility with VMX'en with VM to VM communication, we
0786          * always return zero wellknown handles.
0787          */
0788 
0789         *buf_size = 0;
0790         *pbuf = NULL;
0791         result = VMCI_SUCCESS;
0792         break;
0793 
0794     case VMCI_DOORBELL_CPT_STATE:
0795         result = vmci_ctx_get_chkpt_doorbells(context, buf_size, pbuf);
0796         break;
0797 
0798     default:
0799         pr_devel("Invalid cpt state (type=%d)\n", cpt_type);
0800         result = VMCI_ERROR_INVALID_ARGS;
0801         break;
0802     }
0803 
0804     spin_unlock(&context->lock);
0805     vmci_ctx_put(context);
0806 
0807     return result;
0808 }
0809 
0810 /*
0811  * Set current context's checkpoint state of given type.
0812  */
0813 int vmci_ctx_set_chkpt_state(u32 context_id,
0814                  u32 cpt_type,
0815                  u32 buf_size,
0816                  void *cpt_buf)
0817 {
0818     u32 i;
0819     u32 current_id;
0820     int result = VMCI_SUCCESS;
0821     u32 num_ids = buf_size / sizeof(u32);
0822 
0823     if (cpt_type == VMCI_WELLKNOWN_CPT_STATE && num_ids > 0) {
0824         /*
0825          * We would end up here if VMX with VM to VM communication
0826          * attempts to restore a checkpoint with wellknown handles.
0827          */
0828         pr_warn("Attempt to restore checkpoint with obsolete wellknown handles\n");
0829         return VMCI_ERROR_OBSOLETE;
0830     }
0831 
0832     if (cpt_type != VMCI_NOTIFICATION_CPT_STATE) {
0833         pr_devel("Invalid cpt state (type=%d)\n", cpt_type);
0834         return VMCI_ERROR_INVALID_ARGS;
0835     }
0836 
0837     for (i = 0; i < num_ids && result == VMCI_SUCCESS; i++) {
0838         current_id = ((u32 *)cpt_buf)[i];
0839         result = vmci_ctx_add_notification(context_id, current_id);
0840         if (result != VMCI_SUCCESS)
0841             break;
0842     }
0843     if (result != VMCI_SUCCESS)
0844         pr_devel("Failed to set cpt state (type=%d) (error=%d)\n",
0845              cpt_type, result);
0846 
0847     return result;
0848 }
0849 
0850 /*
0851  * Retrieves the specified context's pending notifications in the
0852  * form of a handle array. The handle arrays returned are the
0853  * actual data - not a copy and should not be modified by the
0854  * caller. They must be released using
0855  * vmci_ctx_rcv_notifications_release.
0856  */
0857 int vmci_ctx_rcv_notifications_get(u32 context_id,
0858                    struct vmci_handle_arr **db_handle_array,
0859                    struct vmci_handle_arr **qp_handle_array)
0860 {
0861     struct vmci_ctx *context;
0862     int result = VMCI_SUCCESS;
0863 
0864     context = vmci_ctx_get(context_id);
0865     if (context == NULL)
0866         return VMCI_ERROR_NOT_FOUND;
0867 
0868     spin_lock(&context->lock);
0869 
0870     *db_handle_array = context->pending_doorbell_array;
0871     context->pending_doorbell_array =
0872         vmci_handle_arr_create(0, VMCI_MAX_GUEST_DOORBELL_COUNT);
0873     if (!context->pending_doorbell_array) {
0874         context->pending_doorbell_array = *db_handle_array;
0875         *db_handle_array = NULL;
0876         result = VMCI_ERROR_NO_MEM;
0877     }
0878     *qp_handle_array = NULL;
0879 
0880     spin_unlock(&context->lock);
0881     vmci_ctx_put(context);
0882 
0883     return result;
0884 }
0885 
0886 /*
0887  * Releases handle arrays with pending notifications previously
0888  * retrieved using vmci_ctx_rcv_notifications_get. If the
0889  * notifications were not successfully handed over to the guest,
0890  * success must be false.
0891  */
0892 void vmci_ctx_rcv_notifications_release(u32 context_id,
0893                     struct vmci_handle_arr *db_handle_array,
0894                     struct vmci_handle_arr *qp_handle_array,
0895                     bool success)
0896 {
0897     struct vmci_ctx *context = vmci_ctx_get(context_id);
0898 
0899     spin_lock(&context->lock);
0900     if (!success) {
0901         struct vmci_handle handle;
0902 
0903         /*
0904          * New notifications may have been added while we were not
0905          * holding the context lock, so we transfer any new pending
0906          * doorbell notifications to the old array, and reinstate the
0907          * old array.
0908          */
0909 
0910         handle = vmci_handle_arr_remove_tail(
0911                     context->pending_doorbell_array);
0912         while (!vmci_handle_is_invalid(handle)) {
0913             if (!vmci_handle_arr_has_entry(db_handle_array,
0914                                handle)) {
0915                 vmci_handle_arr_append_entry(
0916                         &db_handle_array, handle);
0917             }
0918             handle = vmci_handle_arr_remove_tail(
0919                     context->pending_doorbell_array);
0920         }
0921         vmci_handle_arr_destroy(context->pending_doorbell_array);
0922         context->pending_doorbell_array = db_handle_array;
0923         db_handle_array = NULL;
0924     } else {
0925         ctx_clear_notify_call(context);
0926     }
0927     spin_unlock(&context->lock);
0928     vmci_ctx_put(context);
0929 
0930     if (db_handle_array)
0931         vmci_handle_arr_destroy(db_handle_array);
0932 
0933     if (qp_handle_array)
0934         vmci_handle_arr_destroy(qp_handle_array);
0935 }
0936 
0937 /*
0938  * Registers that a new doorbell handle has been allocated by the
0939  * context. Only doorbell handles registered can be notified.
0940  */
0941 int vmci_ctx_dbell_create(u32 context_id, struct vmci_handle handle)
0942 {
0943     struct vmci_ctx *context;
0944     int result;
0945 
0946     if (context_id == VMCI_INVALID_ID || vmci_handle_is_invalid(handle))
0947         return VMCI_ERROR_INVALID_ARGS;
0948 
0949     context = vmci_ctx_get(context_id);
0950     if (context == NULL)
0951         return VMCI_ERROR_NOT_FOUND;
0952 
0953     spin_lock(&context->lock);
0954     if (!vmci_handle_arr_has_entry(context->doorbell_array, handle))
0955         result = vmci_handle_arr_append_entry(&context->doorbell_array,
0956                               handle);
0957     else
0958         result = VMCI_ERROR_DUPLICATE_ENTRY;
0959 
0960     spin_unlock(&context->lock);
0961     vmci_ctx_put(context);
0962 
0963     return result;
0964 }
0965 
0966 /*
0967  * Unregisters a doorbell handle that was previously registered
0968  * with vmci_ctx_dbell_create.
0969  */
0970 int vmci_ctx_dbell_destroy(u32 context_id, struct vmci_handle handle)
0971 {
0972     struct vmci_ctx *context;
0973     struct vmci_handle removed_handle;
0974 
0975     if (context_id == VMCI_INVALID_ID || vmci_handle_is_invalid(handle))
0976         return VMCI_ERROR_INVALID_ARGS;
0977 
0978     context = vmci_ctx_get(context_id);
0979     if (context == NULL)
0980         return VMCI_ERROR_NOT_FOUND;
0981 
0982     spin_lock(&context->lock);
0983     removed_handle =
0984         vmci_handle_arr_remove_entry(context->doorbell_array, handle);
0985     vmci_handle_arr_remove_entry(context->pending_doorbell_array, handle);
0986     spin_unlock(&context->lock);
0987 
0988     vmci_ctx_put(context);
0989 
0990     return vmci_handle_is_invalid(removed_handle) ?
0991         VMCI_ERROR_NOT_FOUND : VMCI_SUCCESS;
0992 }
0993 
0994 /*
0995  * Unregisters all doorbell handles that were previously
0996  * registered with vmci_ctx_dbell_create.
0997  */
0998 int vmci_ctx_dbell_destroy_all(u32 context_id)
0999 {
1000     struct vmci_ctx *context;
1001     struct vmci_handle handle;
1002 
1003     if (context_id == VMCI_INVALID_ID)
1004         return VMCI_ERROR_INVALID_ARGS;
1005 
1006     context = vmci_ctx_get(context_id);
1007     if (context == NULL)
1008         return VMCI_ERROR_NOT_FOUND;
1009 
1010     spin_lock(&context->lock);
1011     do {
1012         struct vmci_handle_arr *arr = context->doorbell_array;
1013         handle = vmci_handle_arr_remove_tail(arr);
1014     } while (!vmci_handle_is_invalid(handle));
1015     do {
1016         struct vmci_handle_arr *arr = context->pending_doorbell_array;
1017         handle = vmci_handle_arr_remove_tail(arr);
1018     } while (!vmci_handle_is_invalid(handle));
1019     spin_unlock(&context->lock);
1020 
1021     vmci_ctx_put(context);
1022 
1023     return VMCI_SUCCESS;
1024 }
1025 
1026 /*
1027  * Registers a notification of a doorbell handle initiated by the
1028  * specified source context. The notification of doorbells are
1029  * subject to the same isolation rules as datagram delivery. To
1030  * allow host side senders of notifications a finer granularity
1031  * of sender rights than those assigned to the sending context
1032  * itself, the host context is required to specify a different
1033  * set of privilege flags that will override the privileges of
1034  * the source context.
1035  */
1036 int vmci_ctx_notify_dbell(u32 src_cid,
1037               struct vmci_handle handle,
1038               u32 src_priv_flags)
1039 {
1040     struct vmci_ctx *dst_context;
1041     int result;
1042 
1043     if (vmci_handle_is_invalid(handle))
1044         return VMCI_ERROR_INVALID_ARGS;
1045 
1046     /* Get the target VM's VMCI context. */
1047     dst_context = vmci_ctx_get(handle.context);
1048     if (!dst_context) {
1049         pr_devel("Invalid context (ID=0x%x)\n", handle.context);
1050         return VMCI_ERROR_NOT_FOUND;
1051     }
1052 
1053     if (src_cid != handle.context) {
1054         u32 dst_priv_flags;
1055 
1056         if (VMCI_CONTEXT_IS_VM(src_cid) &&
1057             VMCI_CONTEXT_IS_VM(handle.context)) {
1058             pr_devel("Doorbell notification from VM to VM not supported (src=0x%x, dst=0x%x)\n",
1059                  src_cid, handle.context);
1060             result = VMCI_ERROR_DST_UNREACHABLE;
1061             goto out;
1062         }
1063 
1064         result = vmci_dbell_get_priv_flags(handle, &dst_priv_flags);
1065         if (result < VMCI_SUCCESS) {
1066             pr_warn("Failed to get privilege flags for destination (handle=0x%x:0x%x)\n",
1067                 handle.context, handle.resource);
1068             goto out;
1069         }
1070 
1071         if (src_cid != VMCI_HOST_CONTEXT_ID ||
1072             src_priv_flags == VMCI_NO_PRIVILEGE_FLAGS) {
1073             src_priv_flags = vmci_context_get_priv_flags(src_cid);
1074         }
1075 
1076         if (vmci_deny_interaction(src_priv_flags, dst_priv_flags)) {
1077             result = VMCI_ERROR_NO_ACCESS;
1078             goto out;
1079         }
1080     }
1081 
1082     if (handle.context == VMCI_HOST_CONTEXT_ID) {
1083         result = vmci_dbell_host_context_notify(src_cid, handle);
1084     } else {
1085         spin_lock(&dst_context->lock);
1086 
1087         if (!vmci_handle_arr_has_entry(dst_context->doorbell_array,
1088                            handle)) {
1089             result = VMCI_ERROR_NOT_FOUND;
1090         } else {
1091             if (!vmci_handle_arr_has_entry(
1092                     dst_context->pending_doorbell_array,
1093                     handle)) {
1094                 result = vmci_handle_arr_append_entry(
1095                     &dst_context->pending_doorbell_array,
1096                     handle);
1097                 if (result == VMCI_SUCCESS) {
1098                     ctx_signal_notify(dst_context);
1099                     wake_up(&dst_context->host_context.wait_queue);
1100                 }
1101             } else {
1102                 result = VMCI_SUCCESS;
1103             }
1104         }
1105         spin_unlock(&dst_context->lock);
1106     }
1107 
1108  out:
1109     vmci_ctx_put(dst_context);
1110 
1111     return result;
1112 }
1113 
1114 bool vmci_ctx_supports_host_qp(struct vmci_ctx *context)
1115 {
1116     return context && context->user_version >= VMCI_VERSION_HOSTQP;
1117 }
1118 
1119 /*
1120  * Registers that a new queue pair handle has been allocated by
1121  * the context.
1122  */
1123 int vmci_ctx_qp_create(struct vmci_ctx *context, struct vmci_handle handle)
1124 {
1125     int result;
1126 
1127     if (context == NULL || vmci_handle_is_invalid(handle))
1128         return VMCI_ERROR_INVALID_ARGS;
1129 
1130     if (!vmci_handle_arr_has_entry(context->queue_pair_array, handle))
1131         result = vmci_handle_arr_append_entry(
1132             &context->queue_pair_array, handle);
1133     else
1134         result = VMCI_ERROR_DUPLICATE_ENTRY;
1135 
1136     return result;
1137 }
1138 
1139 /*
1140  * Unregisters a queue pair handle that was previously registered
1141  * with vmci_ctx_qp_create.
1142  */
1143 int vmci_ctx_qp_destroy(struct vmci_ctx *context, struct vmci_handle handle)
1144 {
1145     struct vmci_handle hndl;
1146 
1147     if (context == NULL || vmci_handle_is_invalid(handle))
1148         return VMCI_ERROR_INVALID_ARGS;
1149 
1150     hndl = vmci_handle_arr_remove_entry(context->queue_pair_array, handle);
1151 
1152     return vmci_handle_is_invalid(hndl) ?
1153         VMCI_ERROR_NOT_FOUND : VMCI_SUCCESS;
1154 }
1155 
1156 /*
1157  * Determines whether a given queue pair handle is registered
1158  * with the given context.
1159  */
1160 bool vmci_ctx_qp_exists(struct vmci_ctx *context, struct vmci_handle handle)
1161 {
1162     if (context == NULL || vmci_handle_is_invalid(handle))
1163         return false;
1164 
1165     return vmci_handle_arr_has_entry(context->queue_pair_array, handle);
1166 }
1167 
1168 /*
1169  * vmci_context_get_priv_flags() - Retrieve privilege flags.
1170  * @context_id: The context ID of the VMCI context.
1171  *
1172  * Retrieves privilege flags of the given VMCI context ID.
1173  */
1174 u32 vmci_context_get_priv_flags(u32 context_id)
1175 {
1176     if (vmci_host_code_active()) {
1177         u32 flags;
1178         struct vmci_ctx *context;
1179 
1180         context = vmci_ctx_get(context_id);
1181         if (!context)
1182             return VMCI_LEAST_PRIVILEGE_FLAGS;
1183 
1184         flags = context->priv_flags;
1185         vmci_ctx_put(context);
1186         return flags;
1187     }
1188     return VMCI_NO_PRIVILEGE_FLAGS;
1189 }
1190 EXPORT_SYMBOL_GPL(vmci_context_get_priv_flags);
1191 
1192 /*
1193  * vmci_is_context_owner() - Determimnes if user is the context owner
1194  * @context_id: The context ID of the VMCI context.
1195  * @uid:        The host user id (real kernel value).
1196  *
1197  * Determines whether a given UID is the owner of given VMCI context.
1198  */
1199 bool vmci_is_context_owner(u32 context_id, kuid_t uid)
1200 {
1201     bool is_owner = false;
1202 
1203     if (vmci_host_code_active()) {
1204         struct vmci_ctx *context = vmci_ctx_get(context_id);
1205         if (context) {
1206             if (context->cred)
1207                 is_owner = uid_eq(context->cred->uid, uid);
1208             vmci_ctx_put(context);
1209         }
1210     }
1211 
1212     return is_owner;
1213 }
1214 EXPORT_SYMBOL_GPL(vmci_is_context_owner);