trusty-log.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /*
  2. * Copyright (C) 2015 Google, Inc.
  3. *
  4. * This software is licensed under the terms of the GNU General Public
  5. * License version 2, as published by the Free Software Foundation, and
  6. * may be copied, distributed, and modified under those terms.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. */
  14. #include <linux/platform_device.h>
  15. #include <linux/trusty/smcall.h>
  16. #include <linux/trusty/trusty.h>
  17. #include <linux/notifier.h>
  18. #include <linux/slab.h>
  19. #include <linux/mm.h>
  20. #include <linux/log2.h>
  21. #include <asm/page.h>
  22. #include "trusty-log.h"
  23. #define TRUSTY_LOG_SIZE (PAGE_SIZE * 32)
  24. #define TRUSTY_LINE_BUFFER_SIZE 256
  25. struct trusty_log_state {
  26. struct device *dev;
  27. struct device *trusty_dev;
  28. /*
  29. * This lock is here to ensure only one consumer will read
  30. * from the log ring buffer at a time.
  31. */
  32. spinlock_t lock;
  33. struct log_rb *log;
  34. uint32_t get;
  35. struct page *log_pages;
  36. struct notifier_block call_notifier;
  37. struct notifier_block panic_notifier;
  38. char line_buffer[TRUSTY_LINE_BUFFER_SIZE];
  39. };
  40. static int log_read_line(struct trusty_log_state *s, int put, int get)
  41. {
  42. struct log_rb *log = s->log;
  43. int i;
  44. char c = '\0';
  45. size_t max_to_read = min((size_t)(put - get),
  46. sizeof(s->line_buffer) - 1);
  47. size_t mask = log->sz - 1;
  48. for (i = 0; i < max_to_read && c != '\n';)
  49. s->line_buffer[i++] = c = log->data[get++ & mask];
  50. s->line_buffer[i] = '\0';
  51. return i;
  52. }
  53. static void trusty_dump_logs(struct trusty_log_state *s)
  54. {
  55. struct log_rb *log = s->log;
  56. uint32_t get, put, alloc;
  57. int read_chars;
  58. BUG_ON(!is_power_of_2(log->sz));
  59. /*
  60. * For this ring buffer, at any given point, alloc >= put >= get.
  61. * The producer side of the buffer is not locked, so the put and alloc
  62. * pointers must be read in a defined order (put before alloc) so
  63. * that the above condition is maintained. A read barrier is needed
  64. * to make sure the hardware and compiler keep the reads ordered.
  65. */
  66. get = s->get;
  67. while ((put = log->put) != get) {
  68. /* Make sure that the read of put occurs before the read of log data */
  69. rmb();
  70. /* Read a line from the log */
  71. read_chars = log_read_line(s, put, get);
  72. /* Force the loads from log_read_line to complete. */
  73. rmb();
  74. alloc = log->alloc;
  75. /*
  76. * Discard the line that was just read if the data could
  77. * have been corrupted by the producer.
  78. */
  79. if (alloc - get > log->sz) {
  80. pr_err("trusty: log overflow.");
  81. get = alloc - log->sz;
  82. continue;
  83. }
  84. pr_info("trusty: %s", s->line_buffer);
  85. get += read_chars;
  86. }
  87. s->get = get;
  88. }
  89. static int trusty_log_call_notify(struct notifier_block *nb,
  90. unsigned long action, void *data)
  91. {
  92. struct trusty_log_state *s;
  93. unsigned long flags;
  94. if (action != TRUSTY_CALL_RETURNED)
  95. return NOTIFY_DONE;
  96. s = container_of(nb, struct trusty_log_state, call_notifier);
  97. spin_lock_irqsave(&s->lock, flags);
  98. trusty_dump_logs(s);
  99. spin_unlock_irqrestore(&s->lock, flags);
  100. return NOTIFY_OK;
  101. }
  102. static int trusty_log_panic_notify(struct notifier_block *nb,
  103. unsigned long action, void *data)
  104. {
  105. struct trusty_log_state *s;
  106. /*
  107. * Don't grab the spin lock to hold up the panic notifier, even
  108. * though this is racy.
  109. */
  110. s = container_of(nb, struct trusty_log_state, panic_notifier);
  111. pr_info("trusty-log panic notifier - trusty version %s",
  112. trusty_version_str_get(s->trusty_dev));
  113. trusty_dump_logs(s);
  114. return NOTIFY_OK;
  115. }
  116. static bool trusty_supports_logging(struct device *device)
  117. {
  118. int result;
  119. result = trusty_std_call32(device, SMC_SC_SHARED_LOG_VERSION,
  120. TRUSTY_LOG_API_VERSION, 0, 0);
  121. if (result == SM_ERR_UNDEFINED_SMC) {
  122. pr_info("trusty-log not supported on secure side.\n");
  123. return false;
  124. } else if (result < 0) {
  125. pr_err("trusty std call (SMC_SC_SHARED_LOG_VERSION) failed: %d\n",
  126. result);
  127. return false;
  128. }
  129. if (result == TRUSTY_LOG_API_VERSION) {
  130. return true;
  131. } else {
  132. pr_info("trusty-log unsupported api version: %d, supported: %d\n",
  133. result, TRUSTY_LOG_API_VERSION);
  134. return false;
  135. }
  136. }
  137. static int trusty_log_probe(struct platform_device *pdev)
  138. {
  139. struct trusty_log_state *s;
  140. int result;
  141. phys_addr_t pa;
  142. dev_dbg(&pdev->dev, "%s\n", __func__);
  143. if (!trusty_supports_logging(pdev->dev.parent)) {
  144. return -ENXIO;
  145. }
  146. s = kzalloc(sizeof(*s), GFP_KERNEL);
  147. if (!s) {
  148. result = -ENOMEM;
  149. goto error_alloc_state;
  150. }
  151. spin_lock_init(&s->lock);
  152. s->dev = &pdev->dev;
  153. s->trusty_dev = s->dev->parent;
  154. s->get = 0;
  155. s->log_pages = alloc_pages(GFP_KERNEL | __GFP_ZERO,
  156. get_order(TRUSTY_LOG_SIZE));
  157. if (!s->log_pages) {
  158. result = -ENOMEM;
  159. goto error_alloc_log;
  160. }
  161. s->log = page_address(s->log_pages);
  162. pa = page_to_phys(s->log_pages);
  163. result = trusty_std_call32(s->trusty_dev,
  164. SMC_SC_SHARED_LOG_ADD,
  165. (u32)(pa), (u32)(pa >> 32),
  166. TRUSTY_LOG_SIZE);
  167. if (result < 0) {
  168. pr_err("trusty std call (SMC_SC_SHARED_LOG_ADD) failed: %d %pa\n",
  169. result, &pa);
  170. goto error_std_call;
  171. }
  172. s->call_notifier.notifier_call = trusty_log_call_notify;
  173. result = trusty_call_notifier_register(s->trusty_dev,
  174. &s->call_notifier);
  175. if (result < 0) {
  176. dev_err(&pdev->dev,
  177. "failed to register trusty call notifier\n");
  178. goto error_call_notifier;
  179. }
  180. s->panic_notifier.notifier_call = trusty_log_panic_notify;
  181. result = atomic_notifier_chain_register(&panic_notifier_list,
  182. &s->panic_notifier);
  183. if (result < 0) {
  184. dev_err(&pdev->dev,
  185. "failed to register panic notifier\n");
  186. goto error_panic_notifier;
  187. }
  188. platform_set_drvdata(pdev, s);
  189. return 0;
  190. error_panic_notifier:
  191. trusty_call_notifier_unregister(s->trusty_dev, &s->call_notifier);
  192. error_call_notifier:
  193. trusty_std_call32(s->trusty_dev, SMC_SC_SHARED_LOG_RM,
  194. (u32)pa, (u32)(pa >> 32), 0);
  195. error_std_call:
  196. __free_pages(s->log_pages, get_order(TRUSTY_LOG_SIZE));
  197. error_alloc_log:
  198. kfree(s);
  199. error_alloc_state:
  200. return result;
  201. }
  202. static int trusty_log_remove(struct platform_device *pdev)
  203. {
  204. int result;
  205. struct trusty_log_state *s = platform_get_drvdata(pdev);
  206. phys_addr_t pa = page_to_phys(s->log_pages);
  207. dev_dbg(&pdev->dev, "%s\n", __func__);
  208. atomic_notifier_chain_unregister(&panic_notifier_list,
  209. &s->panic_notifier);
  210. trusty_call_notifier_unregister(s->trusty_dev, &s->call_notifier);
  211. result = trusty_std_call32(s->trusty_dev, SMC_SC_SHARED_LOG_RM,
  212. (u32)pa, (u32)(pa >> 32), 0);
  213. if (result) {
  214. pr_err("trusty std call (SMC_SC_SHARED_LOG_RM) failed: %d\n",
  215. result);
  216. }
  217. __free_pages(s->log_pages, get_order(TRUSTY_LOG_SIZE));
  218. kfree(s);
  219. return 0;
  220. }
  221. static const struct of_device_id trusty_test_of_match[] = {
  222. { .compatible = "android,trusty-log-v1", },
  223. {},
  224. };
  225. static struct platform_driver trusty_log_driver = {
  226. .probe = trusty_log_probe,
  227. .remove = trusty_log_remove,
  228. .driver = {
  229. .name = "trusty-log",
  230. .owner = THIS_MODULE,
  231. .of_match_table = trusty_test_of_match,
  232. },
  233. };
  234. module_platform_driver(trusty_log_driver);