khab.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  5. */
  6. #include "hab.h"
  7. #include <linux/module.h>
  8. int32_t habmm_socket_open(int32_t *handle, uint32_t mm_ip_id,
  9. uint32_t timeout, uint32_t flags)
  10. {
  11. while (unlikely(!READ_ONCE(hab_driver.hab_init_success))) {
  12. pr_info_once("opening on mmid %d when hab has not completed init\n",
  13. mm_ip_id);
  14. schedule();
  15. }
  16. return hab_vchan_open(hab_driver.kctx, mm_ip_id, handle,
  17. timeout, flags);
  18. }
  19. EXPORT_SYMBOL(habmm_socket_open);
  20. int32_t habmm_socket_close(int32_t handle)
  21. {
  22. /*
  23. * The ctx_lock read-side path calls frequently, while the
  24. * write-side path calls less. In order to avoid disabling
  25. * bh on the read side of ctx_lock, do not support calling
  26. * this function in interrupt context. Otherwise you may
  27. * run into serious deadlock issues.
  28. */
  29. WARN_ON(in_irq() || in_serving_softirq());
  30. return hab_vchan_close(hab_driver.kctx, handle);
  31. }
  32. EXPORT_SYMBOL(habmm_socket_close);
  33. int32_t habmm_socket_send(int32_t handle, void *src_buff,
  34. uint32_t size_bytes, uint32_t flags)
  35. {
  36. struct hab_send param = {0};
  37. param.vcid = handle;
  38. param.data = (uint64_t)(uintptr_t)src_buff;
  39. param.sizebytes = size_bytes;
  40. param.flags = flags;
  41. return hab_vchan_send(hab_driver.kctx, handle,
  42. size_bytes, src_buff, flags);
  43. }
  44. EXPORT_SYMBOL(habmm_socket_send);
  45. int32_t habmm_socket_recv(int32_t handle, void *dst_buff, uint32_t *size_bytes,
  46. uint32_t timeout, uint32_t flags)
  47. {
  48. int ret = 0;
  49. struct hab_message *msg = NULL;
  50. void **scatter_buf = NULL;
  51. int i = 0;
  52. if (!size_bytes || !dst_buff)
  53. return -EINVAL;
  54. ret = hab_vchan_recv(hab_driver.kctx, &msg, handle, size_bytes, timeout, flags);
  55. if (ret == 0 && msg) {
  56. if (unlikely(msg->scatter)) {
  57. scatter_buf = (void **)msg->data;
  58. /* The maximum size of msg is limited in hab_msg_alloc*/
  59. for (i = 0; i < msg->sizebytes / PAGE_SIZE; i++)
  60. memcpy((char *)((uint64_t)dst_buff
  61. + (uint64_t)(i * PAGE_SIZE)), scatter_buf[i], PAGE_SIZE);
  62. if (msg->sizebytes % PAGE_SIZE)
  63. memcpy((char *)((uint64_t)dst_buff
  64. + (uint64_t)(i * PAGE_SIZE)), scatter_buf[i],
  65. msg->sizebytes % PAGE_SIZE);
  66. } else
  67. memcpy(dst_buff, msg->data, msg->sizebytes);
  68. } else if (ret && msg) {
  69. pr_warn("vcid %X recv failed %d but msg is still received %zd bytes\n",
  70. handle, ret, msg->sizebytes);
  71. }
  72. if (msg)
  73. hab_msg_free(msg);
  74. return ret;
  75. }
  76. EXPORT_SYMBOL(habmm_socket_recv);
  77. int32_t habmm_export(int32_t handle, void *buff_to_share, uint32_t size_bytes,
  78. uint32_t *export_id, uint32_t flags)
  79. {
  80. int ret;
  81. struct hab_export param = {0};
  82. if (!export_id)
  83. return -EINVAL;
  84. param.vcid = handle;
  85. param.buffer = (uint64_t)(uintptr_t)buff_to_share;
  86. param.sizebytes = size_bytes;
  87. param.flags = flags;
  88. ret = hab_mem_export(hab_driver.kctx, &param, 1);
  89. *export_id = param.exportid;
  90. return ret;
  91. }
  92. EXPORT_SYMBOL(habmm_export);
  93. int32_t habmm_unexport(int32_t handle, uint32_t export_id, uint32_t flags)
  94. {
  95. struct hab_unexport param = {0};
  96. param.vcid = handle;
  97. param.exportid = export_id;
  98. return hab_mem_unexport(hab_driver.kctx, &param, 1);
  99. }
  100. EXPORT_SYMBOL(habmm_unexport);
  101. int32_t habmm_import(int32_t handle, void **buff_shared, uint32_t size_bytes,
  102. uint32_t export_id, uint32_t flags)
  103. {
  104. int ret;
  105. struct hab_import param = {0};
  106. if (!buff_shared)
  107. return -EINVAL;
  108. param.vcid = handle;
  109. param.sizebytes = size_bytes;
  110. param.exportid = export_id;
  111. param.flags = flags;
  112. ret = hab_mem_import(hab_driver.kctx, &param, 1);
  113. if (!ret)
  114. *buff_shared = (void *)(uintptr_t)param.kva;
  115. return ret;
  116. }
  117. EXPORT_SYMBOL(habmm_import);
  118. int32_t habmm_unimport(int32_t handle,
  119. uint32_t export_id,
  120. void *buff_shared,
  121. uint32_t flags)
  122. {
  123. struct hab_unimport param = {0};
  124. param.vcid = handle;
  125. param.exportid = export_id;
  126. param.kva = (uint64_t)(uintptr_t)buff_shared;
  127. return hab_mem_unimport(hab_driver.kctx, &param, 1);
  128. }
  129. EXPORT_SYMBOL(habmm_unimport);
  130. int32_t habmm_socket_query(int32_t handle,
  131. struct hab_socket_info *info,
  132. uint32_t flags)
  133. {
  134. int ret;
  135. uint64_t ids;
  136. char nm[VMNAME_SIZE * 2];
  137. if (!info)
  138. return -EINVAL;
  139. ret = hab_vchan_query(hab_driver.kctx, handle, &ids, nm, sizeof(nm), 1);
  140. if (!ret) {
  141. info->vmid_local = ids & 0xFFFFFFFF;
  142. info->vmid_remote = (ids & 0xFFFFFFFF00000000UL) > 32;
  143. strscpy(info->vmname_local, nm, sizeof(info->vmname_local));
  144. strscpy(info->vmname_remote, &nm[sizeof(info->vmname_local)],
  145. sizeof(info->vmname_remote));
  146. }
  147. return ret;
  148. }
  149. EXPORT_SYMBOL(habmm_socket_query);