async.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
  4. */
  5. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  6. #include "qcomtee.h"
  7. #define QCOMTEE_ASYNC_VERSION_1_0 0x00010000U /* Maj: 0x0001, Min: 0x0000. */
  8. #define QCOMTEE_ASYNC_VERSION_1_1 0x00010001U /* Maj: 0x0001, Min: 0x0001. */
  9. #define QCOMTEE_ASYNC_VERSION_1_2 0x00010002U /* Maj: 0x0001, Min: 0x0002. */
  10. #define QCOMTEE_ASYNC_VERSION_CURRENT QCOMTEE_ASYNC_VERSION_1_2
  11. #define QCOMTEE_ASYNC_VERSION_MAJOR(n) upper_16_bits(n)
  12. #define QCOMTEE_ASYNC_VERSION_MINOR(n) lower_16_bits(n)
  13. #define QCOMTEE_ASYNC_VERSION_CURRENT_MAJOR \
  14. QCOMTEE_ASYNC_VERSION_MAJOR(QCOMTEE_ASYNC_VERSION_CURRENT)
  15. #define QCOMTEE_ASYNC_VERSION_CURRENT_MINOR \
  16. QCOMTEE_ASYNC_VERSION_MINOR(QCOMTEE_ASYNC_VERSION_CURRENT)
  17. /**
  18. * struct qcomtee_async_msg_hdr - Asynchronous message header format.
  19. * @version: current async protocol version of the remote endpoint.
  20. * @op: async operation.
  21. *
  22. * @version specifies the endpoint's (QTEE or driver) supported async protocol.
  23. * For example, if QTEE sets @version to %QCOMTEE_ASYNC_VERSION_1_1, QTEE
  24. * handles operations supported in %QCOMTEE_ASYNC_VERSION_1_1 or
  25. * %QCOMTEE_ASYNC_VERSION_1_0. @op determines the message format.
  26. */
  27. struct qcomtee_async_msg_hdr {
  28. u32 version;
  29. u32 op;
  30. };
  31. /* Size of an empty async message. */
  32. #define QCOMTEE_ASYNC_MSG_ZERO sizeof(struct qcomtee_async_msg_hdr)
  33. /**
  34. * struct qcomtee_async_release_msg - Release asynchronous message.
  35. * @hdr: message header as &struct qcomtee_async_msg_hdr.
  36. * @counts: number of objects in @object_ids.
  37. * @object_ids: array of object IDs that should be released.
  38. *
  39. * Available in Maj = 0x0001, Min >= 0x0000.
  40. */
  41. struct qcomtee_async_release_msg {
  42. struct qcomtee_async_msg_hdr hdr;
  43. u32 counts;
  44. u32 object_ids[] __counted_by(counts);
  45. };
  46. /**
  47. * qcomtee_get_async_buffer() - Get the start of the asynchronous message.
  48. * @oic: context used for the current invocation.
  49. * @async_buffer: return buffer to extract from or fill in async messages.
  50. *
  51. * If @oic is used for direct object invocation, the whole outbound buffer
  52. * is available for the async message. If @oic is used for a callback request,
  53. * the tail of the outbound buffer (after the callback request message) is
  54. * available for the async message.
  55. *
  56. * The start of the async buffer is aligned, see qcomtee_msg_offset_align().
  57. */
  58. static void qcomtee_get_async_buffer(struct qcomtee_object_invoke_ctx *oic,
  59. struct qcomtee_buffer *async_buffer)
  60. {
  61. struct qcomtee_msg_callback *msg;
  62. unsigned int offset;
  63. int i;
  64. if (!(oic->flags & QCOMTEE_OIC_FLAG_BUSY)) {
  65. /* The outbound buffer is empty. Using the whole buffer. */
  66. offset = 0;
  67. } else {
  68. msg = (struct qcomtee_msg_callback *)oic->out_msg.addr;
  69. /* Start offset in a message for buffer arguments. */
  70. offset = qcomtee_msg_buffer_args(struct qcomtee_msg_callback,
  71. qcomtee_msg_args(msg));
  72. /* Add size of IB arguments. */
  73. qcomtee_msg_for_each_input_buffer(i, msg)
  74. offset += qcomtee_msg_offset_align(msg->args[i].b.size);
  75. /* Add size of OB arguments. */
  76. qcomtee_msg_for_each_output_buffer(i, msg)
  77. offset += qcomtee_msg_offset_align(msg->args[i].b.size);
  78. }
  79. async_buffer->addr = oic->out_msg.addr + offset;
  80. async_buffer->size = oic->out_msg.size - offset;
  81. }
  82. /**
  83. * async_release() - Process QTEE async release requests.
  84. * @oic: context used for the current invocation.
  85. * @msg: async message for object release.
  86. * @size: size of the async buffer available.
  87. *
  88. * Return: Size of the outbound buffer used when processing @msg.
  89. */
  90. static size_t async_release(struct qcomtee_object_invoke_ctx *oic,
  91. struct qcomtee_async_msg_hdr *async_msg,
  92. size_t size)
  93. {
  94. struct qcomtee_async_release_msg *msg;
  95. struct qcomtee_object *object;
  96. int i;
  97. msg = (struct qcomtee_async_release_msg *)async_msg;
  98. for (i = 0; i < msg->counts; i++) {
  99. object = qcomtee_idx_erase(oic, msg->object_ids[i]);
  100. qcomtee_object_put(object);
  101. }
  102. return struct_size(msg, object_ids, msg->counts);
  103. }
  104. /**
  105. * qcomtee_fetch_async_reqs() - Fetch and process asynchronous messages.
  106. * @oic: context used for the current invocation.
  107. *
  108. * Calls handlers to process the requested operations in the async message.
  109. * Currently, only supports async release requests.
  110. */
  111. void qcomtee_fetch_async_reqs(struct qcomtee_object_invoke_ctx *oic)
  112. {
  113. struct qcomtee_async_msg_hdr *async_msg;
  114. struct qcomtee_buffer async_buffer;
  115. size_t consumed, used = 0;
  116. u16 major_ver;
  117. qcomtee_get_async_buffer(oic, &async_buffer);
  118. while (async_buffer.size - used > QCOMTEE_ASYNC_MSG_ZERO) {
  119. async_msg = (struct qcomtee_async_msg_hdr *)(async_buffer.addr +
  120. used);
  121. /*
  122. * QTEE assumes that the unused space of the async buffer is
  123. * zeroed; so if version is zero, the buffer is unused.
  124. */
  125. if (async_msg->version == 0)
  126. goto out;
  127. major_ver = QCOMTEE_ASYNC_VERSION_MAJOR(async_msg->version);
  128. /* Major version mismatch is a compatibility break. */
  129. if (major_ver != QCOMTEE_ASYNC_VERSION_CURRENT_MAJOR) {
  130. pr_err("Async message version mismatch (%u != %u)\n",
  131. major_ver, QCOMTEE_ASYNC_VERSION_CURRENT_MAJOR);
  132. goto out;
  133. }
  134. switch (async_msg->op) {
  135. case QCOMTEE_MSG_OBJECT_OP_RELEASE:
  136. consumed = async_release(oic, async_msg,
  137. async_buffer.size - used);
  138. break;
  139. default:
  140. pr_err("Unsupported async message %u\n", async_msg->op);
  141. goto out;
  142. }
  143. /* Supported operation but unable to parse the message. */
  144. if (!consumed) {
  145. pr_err("Unable to parse async message for op %u\n",
  146. async_msg->op);
  147. goto out;
  148. }
  149. /* Next async message. */
  150. used += qcomtee_msg_offset_align(consumed);
  151. }
  152. out:
  153. /* Reset the async buffer so async requests do not loop to QTEE. */
  154. memzero_explicit(async_buffer.addr, async_buffer.size);
  155. }