vmci_doorbell.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  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. #include <linux/vmw_vmci_defs.h>
  8. #include <linux/vmw_vmci_api.h>
  9. #include <linux/completion.h>
  10. #include <linux/hash.h>
  11. #include <linux/kernel.h>
  12. #include <linux/list.h>
  13. #include <linux/module.h>
  14. #include <linux/sched.h>
  15. #include <linux/slab.h>
  16. #include "vmci_datagram.h"
  17. #include "vmci_doorbell.h"
  18. #include "vmci_resource.h"
  19. #include "vmci_driver.h"
  20. #include "vmci_route.h"
  21. #define VMCI_DOORBELL_INDEX_BITS 6
  22. #define VMCI_DOORBELL_INDEX_TABLE_SIZE (1 << VMCI_DOORBELL_INDEX_BITS)
  23. #define VMCI_DOORBELL_HASH(_idx) hash_32(_idx, VMCI_DOORBELL_INDEX_BITS)
  24. /*
  25. * DoorbellEntry describes the a doorbell notification handle allocated by the
  26. * host.
  27. */
  28. struct dbell_entry {
  29. struct vmci_resource resource;
  30. struct hlist_node node;
  31. struct work_struct work;
  32. vmci_callback notify_cb;
  33. void *client_data;
  34. u32 idx;
  35. u32 priv_flags;
  36. bool run_delayed;
  37. atomic_t active; /* Only used by guest personality */
  38. };
  39. /* The VMCI index table keeps track of currently registered doorbells. */
  40. struct dbell_index_table {
  41. spinlock_t lock; /* Index table lock */
  42. struct hlist_head entries[VMCI_DOORBELL_INDEX_TABLE_SIZE];
  43. };
  44. static struct dbell_index_table vmci_doorbell_it = {
  45. .lock = __SPIN_LOCK_UNLOCKED(vmci_doorbell_it.lock),
  46. };
  47. /*
  48. * The max_notify_idx is one larger than the currently known bitmap index in
  49. * use, and is used to determine how much of the bitmap needs to be scanned.
  50. */
  51. static u32 max_notify_idx;
  52. /*
  53. * The notify_idx_count is used for determining whether there are free entries
  54. * within the bitmap (if notify_idx_count + 1 < max_notify_idx).
  55. */
  56. static u32 notify_idx_count;
  57. /*
  58. * The last_notify_idx_reserved is used to track the last index handed out - in
  59. * the case where multiple handles share a notification index, we hand out
  60. * indexes round robin based on last_notify_idx_reserved.
  61. */
  62. static u32 last_notify_idx_reserved;
  63. /* This is a one entry cache used to by the index allocation. */
  64. static u32 last_notify_idx_released = PAGE_SIZE;
  65. /*
  66. * Utility function that retrieves the privilege flags associated
  67. * with a given doorbell handle. For guest endpoints, the
  68. * privileges are determined by the context ID, but for host
  69. * endpoints privileges are associated with the complete
  70. * handle. Hypervisor endpoints are not yet supported.
  71. */
  72. int vmci_dbell_get_priv_flags(struct vmci_handle handle, u32 *priv_flags)
  73. {
  74. if (priv_flags == NULL || handle.context == VMCI_INVALID_ID)
  75. return VMCI_ERROR_INVALID_ARGS;
  76. if (handle.context == VMCI_HOST_CONTEXT_ID) {
  77. struct dbell_entry *entry;
  78. struct vmci_resource *resource;
  79. resource = vmci_resource_by_handle(handle,
  80. VMCI_RESOURCE_TYPE_DOORBELL);
  81. if (!resource)
  82. return VMCI_ERROR_NOT_FOUND;
  83. entry = container_of(resource, struct dbell_entry, resource);
  84. *priv_flags = entry->priv_flags;
  85. vmci_resource_put(resource);
  86. } else if (handle.context == VMCI_HYPERVISOR_CONTEXT_ID) {
  87. /*
  88. * Hypervisor endpoints for notifications are not
  89. * supported (yet).
  90. */
  91. return VMCI_ERROR_INVALID_ARGS;
  92. } else {
  93. *priv_flags = vmci_context_get_priv_flags(handle.context);
  94. }
  95. return VMCI_SUCCESS;
  96. }
  97. /*
  98. * Find doorbell entry by bitmap index.
  99. */
  100. static struct dbell_entry *dbell_index_table_find(u32 idx)
  101. {
  102. u32 bucket = VMCI_DOORBELL_HASH(idx);
  103. struct dbell_entry *dbell;
  104. hlist_for_each_entry(dbell, &vmci_doorbell_it.entries[bucket],
  105. node) {
  106. if (idx == dbell->idx)
  107. return dbell;
  108. }
  109. return NULL;
  110. }
  111. /*
  112. * Add the given entry to the index table. This willi take a reference to the
  113. * entry's resource so that the entry is not deleted before it is removed from
  114. * the * table.
  115. */
  116. static void dbell_index_table_add(struct dbell_entry *entry)
  117. {
  118. u32 bucket;
  119. u32 new_notify_idx;
  120. vmci_resource_get(&entry->resource);
  121. spin_lock_bh(&vmci_doorbell_it.lock);
  122. /*
  123. * Below we try to allocate an index in the notification
  124. * bitmap with "not too much" sharing between resources. If we
  125. * use less that the full bitmap, we either add to the end if
  126. * there are no unused flags within the currently used area,
  127. * or we search for unused ones. If we use the full bitmap, we
  128. * allocate the index round robin.
  129. */
  130. if (max_notify_idx < PAGE_SIZE || notify_idx_count < PAGE_SIZE) {
  131. if (last_notify_idx_released < max_notify_idx &&
  132. !dbell_index_table_find(last_notify_idx_released)) {
  133. new_notify_idx = last_notify_idx_released;
  134. last_notify_idx_released = PAGE_SIZE;
  135. } else {
  136. bool reused = false;
  137. new_notify_idx = last_notify_idx_reserved;
  138. if (notify_idx_count + 1 < max_notify_idx) {
  139. do {
  140. if (!dbell_index_table_find
  141. (new_notify_idx)) {
  142. reused = true;
  143. break;
  144. }
  145. new_notify_idx = (new_notify_idx + 1) %
  146. max_notify_idx;
  147. } while (new_notify_idx !=
  148. last_notify_idx_released);
  149. }
  150. if (!reused) {
  151. new_notify_idx = max_notify_idx;
  152. max_notify_idx++;
  153. }
  154. }
  155. } else {
  156. new_notify_idx = (last_notify_idx_reserved + 1) % PAGE_SIZE;
  157. }
  158. last_notify_idx_reserved = new_notify_idx;
  159. notify_idx_count++;
  160. entry->idx = new_notify_idx;
  161. bucket = VMCI_DOORBELL_HASH(entry->idx);
  162. hlist_add_head(&entry->node, &vmci_doorbell_it.entries[bucket]);
  163. spin_unlock_bh(&vmci_doorbell_it.lock);
  164. }
  165. /*
  166. * Remove the given entry from the index table. This will release() the
  167. * entry's resource.
  168. */
  169. static void dbell_index_table_remove(struct dbell_entry *entry)
  170. {
  171. spin_lock_bh(&vmci_doorbell_it.lock);
  172. hlist_del_init(&entry->node);
  173. notify_idx_count--;
  174. if (entry->idx == max_notify_idx - 1) {
  175. /*
  176. * If we delete an entry with the maximum known
  177. * notification index, we take the opportunity to
  178. * prune the current max. As there might be other
  179. * unused indices immediately below, we lower the
  180. * maximum until we hit an index in use.
  181. */
  182. while (max_notify_idx > 0 &&
  183. !dbell_index_table_find(max_notify_idx - 1))
  184. max_notify_idx--;
  185. }
  186. last_notify_idx_released = entry->idx;
  187. spin_unlock_bh(&vmci_doorbell_it.lock);
  188. vmci_resource_put(&entry->resource);
  189. }
  190. /*
  191. * Creates a link between the given doorbell handle and the given
  192. * index in the bitmap in the device backend. A notification state
  193. * is created in hypervisor.
  194. */
  195. static int dbell_link(struct vmci_handle handle, u32 notify_idx)
  196. {
  197. struct vmci_doorbell_link_msg link_msg;
  198. link_msg.hdr.dst = vmci_make_handle(VMCI_HYPERVISOR_CONTEXT_ID,
  199. VMCI_DOORBELL_LINK);
  200. link_msg.hdr.src = VMCI_ANON_SRC_HANDLE;
  201. link_msg.hdr.payload_size = sizeof(link_msg) - VMCI_DG_HEADERSIZE;
  202. link_msg.handle = handle;
  203. link_msg.notify_idx = notify_idx;
  204. return vmci_send_datagram(&link_msg.hdr);
  205. }
  206. /*
  207. * Unlinks the given doorbell handle from an index in the bitmap in
  208. * the device backend. The notification state is destroyed in hypervisor.
  209. */
  210. static int dbell_unlink(struct vmci_handle handle)
  211. {
  212. struct vmci_doorbell_unlink_msg unlink_msg;
  213. unlink_msg.hdr.dst = vmci_make_handle(VMCI_HYPERVISOR_CONTEXT_ID,
  214. VMCI_DOORBELL_UNLINK);
  215. unlink_msg.hdr.src = VMCI_ANON_SRC_HANDLE;
  216. unlink_msg.hdr.payload_size = sizeof(unlink_msg) - VMCI_DG_HEADERSIZE;
  217. unlink_msg.handle = handle;
  218. return vmci_send_datagram(&unlink_msg.hdr);
  219. }
  220. /*
  221. * Calls the specified callback in a delayed context.
  222. */
  223. static void dbell_delayed_dispatch(struct work_struct *work)
  224. {
  225. struct dbell_entry *entry = container_of(work,
  226. struct dbell_entry, work);
  227. entry->notify_cb(entry->client_data);
  228. vmci_resource_put(&entry->resource);
  229. }
  230. /*
  231. * Dispatches a doorbell notification to the host context.
  232. */
  233. int vmci_dbell_host_context_notify(u32 src_cid, struct vmci_handle handle)
  234. {
  235. struct dbell_entry *entry;
  236. struct vmci_resource *resource;
  237. if (vmci_handle_is_invalid(handle)) {
  238. pr_devel("Notifying an invalid doorbell (handle=0x%x:0x%x)\n",
  239. handle.context, handle.resource);
  240. return VMCI_ERROR_INVALID_ARGS;
  241. }
  242. resource = vmci_resource_by_handle(handle,
  243. VMCI_RESOURCE_TYPE_DOORBELL);
  244. if (!resource) {
  245. pr_devel("Notifying an unknown doorbell (handle=0x%x:0x%x)\n",
  246. handle.context, handle.resource);
  247. return VMCI_ERROR_NOT_FOUND;
  248. }
  249. entry = container_of(resource, struct dbell_entry, resource);
  250. if (entry->run_delayed) {
  251. if (!schedule_work(&entry->work))
  252. vmci_resource_put(resource);
  253. } else {
  254. entry->notify_cb(entry->client_data);
  255. vmci_resource_put(resource);
  256. }
  257. return VMCI_SUCCESS;
  258. }
  259. /*
  260. * Register the notification bitmap with the host.
  261. */
  262. bool vmci_dbell_register_notification_bitmap(u64 bitmap_ppn)
  263. {
  264. int result;
  265. struct vmci_notify_bm_set_msg bitmap_set_msg = { };
  266. bitmap_set_msg.hdr.dst = vmci_make_handle(VMCI_HYPERVISOR_CONTEXT_ID,
  267. VMCI_SET_NOTIFY_BITMAP);
  268. bitmap_set_msg.hdr.src = VMCI_ANON_SRC_HANDLE;
  269. bitmap_set_msg.hdr.payload_size = sizeof(bitmap_set_msg) -
  270. VMCI_DG_HEADERSIZE;
  271. if (vmci_use_ppn64())
  272. bitmap_set_msg.bitmap_ppn64 = bitmap_ppn;
  273. else
  274. bitmap_set_msg.bitmap_ppn32 = (u32) bitmap_ppn;
  275. result = vmci_send_datagram(&bitmap_set_msg.hdr);
  276. if (result != VMCI_SUCCESS) {
  277. pr_devel("Failed to register (PPN=%llu) as notification bitmap (error=%d)\n",
  278. bitmap_ppn, result);
  279. return false;
  280. }
  281. return true;
  282. }
  283. /*
  284. * Executes or schedules the handlers for a given notify index.
  285. */
  286. static void dbell_fire_entries(u32 notify_idx)
  287. {
  288. u32 bucket = VMCI_DOORBELL_HASH(notify_idx);
  289. struct dbell_entry *dbell;
  290. spin_lock_bh(&vmci_doorbell_it.lock);
  291. hlist_for_each_entry(dbell, &vmci_doorbell_it.entries[bucket], node) {
  292. if (dbell->idx == notify_idx &&
  293. atomic_read(&dbell->active) == 1) {
  294. if (dbell->run_delayed) {
  295. vmci_resource_get(&dbell->resource);
  296. if (!schedule_work(&dbell->work))
  297. vmci_resource_put(&dbell->resource);
  298. } else {
  299. dbell->notify_cb(dbell->client_data);
  300. }
  301. }
  302. }
  303. spin_unlock_bh(&vmci_doorbell_it.lock);
  304. }
  305. /*
  306. * Scans the notification bitmap, collects pending notifications,
  307. * resets the bitmap and invokes appropriate callbacks.
  308. */
  309. void vmci_dbell_scan_notification_entries(u8 *bitmap)
  310. {
  311. u32 idx;
  312. for (idx = 0; idx < max_notify_idx; idx++) {
  313. if (bitmap[idx] & 0x1) {
  314. bitmap[idx] &= ~1;
  315. dbell_fire_entries(idx);
  316. }
  317. }
  318. }
  319. /*
  320. * vmci_doorbell_create() - Creates a doorbell
  321. * @handle: A handle used to track the resource. Can be invalid.
  322. * @flags: Flag that determines context of callback.
  323. * @priv_flags: Privileges flags.
  324. * @notify_cb: The callback to be ivoked when the doorbell fires.
  325. * @client_data: A parameter to be passed to the callback.
  326. *
  327. * Creates a doorbell with the given callback. If the handle is
  328. * VMCI_INVALID_HANDLE, a free handle will be assigned, if
  329. * possible. The callback can be run immediately (potentially with
  330. * locks held - the default) or delayed (in a kernel thread) by
  331. * specifying the flag VMCI_FLAG_DELAYED_CB. If delayed execution
  332. * is selected, a given callback may not be run if the kernel is
  333. * unable to allocate memory for the delayed execution (highly
  334. * unlikely).
  335. */
  336. int vmci_doorbell_create(struct vmci_handle *handle,
  337. u32 flags,
  338. u32 priv_flags,
  339. vmci_callback notify_cb, void *client_data)
  340. {
  341. struct dbell_entry *entry;
  342. struct vmci_handle new_handle;
  343. int result;
  344. if (!handle || !notify_cb || flags & ~VMCI_FLAG_DELAYED_CB ||
  345. priv_flags & ~VMCI_PRIVILEGE_ALL_FLAGS)
  346. return VMCI_ERROR_INVALID_ARGS;
  347. entry = kmalloc_obj(*entry);
  348. if (entry == NULL) {
  349. pr_warn("Failed allocating memory for datagram entry\n");
  350. return VMCI_ERROR_NO_MEM;
  351. }
  352. if (vmci_handle_is_invalid(*handle)) {
  353. u32 context_id = vmci_get_context_id();
  354. if (context_id == VMCI_INVALID_ID) {
  355. pr_warn("Failed to get context ID\n");
  356. result = VMCI_ERROR_NO_RESOURCES;
  357. goto free_mem;
  358. }
  359. /* Let resource code allocate a free ID for us */
  360. new_handle = vmci_make_handle(context_id, VMCI_INVALID_ID);
  361. } else {
  362. bool valid_context = false;
  363. /*
  364. * Validate the handle. We must do both of the checks below
  365. * because we can be acting as both a host and a guest at the
  366. * same time. We always allow the host context ID, since the
  367. * host functionality is in practice always there with the
  368. * unified driver.
  369. */
  370. if (handle->context == VMCI_HOST_CONTEXT_ID ||
  371. (vmci_guest_code_active() &&
  372. vmci_get_context_id() == handle->context)) {
  373. valid_context = true;
  374. }
  375. if (!valid_context || handle->resource == VMCI_INVALID_ID) {
  376. pr_devel("Invalid argument (handle=0x%x:0x%x)\n",
  377. handle->context, handle->resource);
  378. result = VMCI_ERROR_INVALID_ARGS;
  379. goto free_mem;
  380. }
  381. new_handle = *handle;
  382. }
  383. entry->idx = 0;
  384. INIT_HLIST_NODE(&entry->node);
  385. entry->priv_flags = priv_flags;
  386. INIT_WORK(&entry->work, dbell_delayed_dispatch);
  387. entry->run_delayed = flags & VMCI_FLAG_DELAYED_CB;
  388. entry->notify_cb = notify_cb;
  389. entry->client_data = client_data;
  390. atomic_set(&entry->active, 0);
  391. result = vmci_resource_add(&entry->resource,
  392. VMCI_RESOURCE_TYPE_DOORBELL,
  393. new_handle);
  394. if (result != VMCI_SUCCESS) {
  395. pr_warn("Failed to add new resource (handle=0x%x:0x%x), error: %d\n",
  396. new_handle.context, new_handle.resource, result);
  397. goto free_mem;
  398. }
  399. new_handle = vmci_resource_handle(&entry->resource);
  400. if (vmci_guest_code_active()) {
  401. dbell_index_table_add(entry);
  402. result = dbell_link(new_handle, entry->idx);
  403. if (VMCI_SUCCESS != result)
  404. goto destroy_resource;
  405. atomic_set(&entry->active, 1);
  406. }
  407. *handle = new_handle;
  408. return result;
  409. destroy_resource:
  410. dbell_index_table_remove(entry);
  411. vmci_resource_remove(&entry->resource);
  412. free_mem:
  413. kfree(entry);
  414. return result;
  415. }
  416. EXPORT_SYMBOL_GPL(vmci_doorbell_create);
  417. /*
  418. * vmci_doorbell_destroy() - Destroy a doorbell.
  419. * @handle: The handle tracking the resource.
  420. *
  421. * Destroys a doorbell previously created with vmcii_doorbell_create. This
  422. * operation may block waiting for a callback to finish.
  423. */
  424. int vmci_doorbell_destroy(struct vmci_handle handle)
  425. {
  426. struct dbell_entry *entry;
  427. struct vmci_resource *resource;
  428. if (vmci_handle_is_invalid(handle))
  429. return VMCI_ERROR_INVALID_ARGS;
  430. resource = vmci_resource_by_handle(handle,
  431. VMCI_RESOURCE_TYPE_DOORBELL);
  432. if (!resource) {
  433. pr_devel("Failed to destroy doorbell (handle=0x%x:0x%x)\n",
  434. handle.context, handle.resource);
  435. return VMCI_ERROR_NOT_FOUND;
  436. }
  437. entry = container_of(resource, struct dbell_entry, resource);
  438. if (!hlist_unhashed(&entry->node)) {
  439. int result;
  440. dbell_index_table_remove(entry);
  441. result = dbell_unlink(handle);
  442. if (VMCI_SUCCESS != result) {
  443. /*
  444. * The only reason this should fail would be
  445. * an inconsistency between guest and
  446. * hypervisor state, where the guest believes
  447. * it has an active registration whereas the
  448. * hypervisor doesn't. One case where this may
  449. * happen is if a doorbell is unregistered
  450. * following a hibernation at a time where the
  451. * doorbell state hasn't been restored on the
  452. * hypervisor side yet. Since the handle has
  453. * now been removed in the guest, we just
  454. * print a warning and return success.
  455. */
  456. pr_devel("Unlink of doorbell (handle=0x%x:0x%x) unknown by hypervisor (error=%d)\n",
  457. handle.context, handle.resource, result);
  458. }
  459. }
  460. /*
  461. * Now remove the resource from the table. It might still be in use
  462. * after this, in a callback or still on the delayed work queue.
  463. */
  464. vmci_resource_put(&entry->resource);
  465. vmci_resource_remove(&entry->resource);
  466. kfree(entry);
  467. return VMCI_SUCCESS;
  468. }
  469. EXPORT_SYMBOL_GPL(vmci_doorbell_destroy);