stacktrace.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * KVM nVHE hypervisor stack tracing support.
  4. *
  5. * The unwinder implementation depends on the nVHE mode:
  6. *
  7. * 1) Non-protected nVHE mode - the host can directly access the
  8. * HYP stack pages and unwind the HYP stack in EL1. This saves having
  9. * to allocate shared buffers for the host to read the unwinded
  10. * stacktrace.
  11. *
  12. * 2) pKVM (protected nVHE) mode - the host cannot directly access
  13. * the HYP memory. The stack is unwinded in EL2 and dumped to a shared
  14. * buffer where the host can read and print the stacktrace.
  15. *
  16. * Copyright (C) 2022 Google LLC
  17. */
  18. #include <linux/kvm.h>
  19. #include <linux/kvm_host.h>
  20. #include <asm/kvm_mmu.h>
  21. #include <asm/stacktrace/nvhe.h>
  22. static struct stack_info stackinfo_get_overflow(void)
  23. {
  24. struct kvm_nvhe_stacktrace_info *stacktrace_info
  25. = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
  26. unsigned long low = (unsigned long)stacktrace_info->overflow_stack_base;
  27. unsigned long high = low + OVERFLOW_STACK_SIZE;
  28. return (struct stack_info) {
  29. .low = low,
  30. .high = high,
  31. };
  32. }
  33. static struct stack_info stackinfo_get_overflow_kern_va(void)
  34. {
  35. unsigned long low = (unsigned long)this_cpu_ptr_nvhe_sym(overflow_stack);
  36. unsigned long high = low + OVERFLOW_STACK_SIZE;
  37. return (struct stack_info) {
  38. .low = low,
  39. .high = high,
  40. };
  41. }
  42. static struct stack_info stackinfo_get_hyp(void)
  43. {
  44. struct kvm_nvhe_stacktrace_info *stacktrace_info
  45. = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
  46. unsigned long low = (unsigned long)stacktrace_info->stack_base;
  47. unsigned long high = low + NVHE_STACK_SIZE;
  48. return (struct stack_info) {
  49. .low = low,
  50. .high = high,
  51. };
  52. }
  53. static struct stack_info stackinfo_get_hyp_kern_va(void)
  54. {
  55. unsigned long low = (unsigned long)*this_cpu_ptr(&kvm_arm_hyp_stack_base);
  56. unsigned long high = low + NVHE_STACK_SIZE;
  57. return (struct stack_info) {
  58. .low = low,
  59. .high = high,
  60. };
  61. }
  62. /*
  63. * kvm_nvhe_stack_kern_va - Convert KVM nVHE HYP stack addresses to a kernel VAs
  64. *
  65. * The nVHE hypervisor stack is mapped in the flexible 'private' VA range, to
  66. * allow for guard pages below the stack. Consequently, the fixed offset address
  67. * translation macros won't work here.
  68. *
  69. * The kernel VA is calculated as an offset from the kernel VA of the hypervisor
  70. * stack base.
  71. *
  72. * Returns true on success and updates @addr to its corresponding kernel VA;
  73. * otherwise returns false.
  74. */
  75. static bool kvm_nvhe_stack_kern_va(unsigned long *addr, unsigned long size)
  76. {
  77. struct stack_info stack_hyp, stack_kern;
  78. stack_hyp = stackinfo_get_hyp();
  79. stack_kern = stackinfo_get_hyp_kern_va();
  80. if (stackinfo_on_stack(&stack_hyp, *addr, size))
  81. goto found;
  82. stack_hyp = stackinfo_get_overflow();
  83. stack_kern = stackinfo_get_overflow_kern_va();
  84. if (stackinfo_on_stack(&stack_hyp, *addr, size))
  85. goto found;
  86. return false;
  87. found:
  88. *addr = *addr - stack_hyp.low + stack_kern.low;
  89. return true;
  90. }
  91. /*
  92. * Convert a KVN nVHE HYP frame record address to a kernel VA
  93. */
  94. static bool kvm_nvhe_stack_kern_record_va(unsigned long *addr)
  95. {
  96. return kvm_nvhe_stack_kern_va(addr, 16);
  97. }
  98. static int unwind_next(struct unwind_state *state)
  99. {
  100. /*
  101. * The FP is in the hypervisor VA space. Convert it to the kernel VA
  102. * space so it can be unwound by the regular unwind functions.
  103. */
  104. if (!kvm_nvhe_stack_kern_record_va(&state->fp))
  105. return -EINVAL;
  106. return unwind_next_frame_record(state);
  107. }
  108. static void unwind(struct unwind_state *state,
  109. stack_trace_consume_fn consume_entry, void *cookie)
  110. {
  111. while (1) {
  112. int ret;
  113. if (!consume_entry(cookie, state->pc))
  114. break;
  115. ret = unwind_next(state);
  116. if (ret < 0)
  117. break;
  118. }
  119. }
  120. /*
  121. * kvm_nvhe_dump_backtrace_entry - Symbolize and print an nVHE backtrace entry
  122. *
  123. * @arg : the hypervisor offset, used for address translation
  124. * @where : the program counter corresponding to the stack frame
  125. */
  126. static bool kvm_nvhe_dump_backtrace_entry(void *arg, unsigned long where)
  127. {
  128. unsigned long va_mask = GENMASK_ULL(__hyp_va_bits - 1, 0);
  129. unsigned long hyp_offset = (unsigned long)arg;
  130. /* Mask tags and convert to kern addr */
  131. where = (where & va_mask) + hyp_offset;
  132. kvm_err(" [<%016lx>] %pB\n", where, (void *)(where + kaslr_offset()));
  133. return true;
  134. }
  135. static void kvm_nvhe_dump_backtrace_start(void)
  136. {
  137. kvm_err("nVHE call trace:\n");
  138. }
  139. static void kvm_nvhe_dump_backtrace_end(void)
  140. {
  141. kvm_err("---[ end nVHE call trace ]---\n");
  142. }
  143. /*
  144. * hyp_dump_backtrace - Dump the non-protected nVHE backtrace.
  145. *
  146. * @hyp_offset: hypervisor offset, used for address translation.
  147. *
  148. * The host can directly access HYP stack pages in non-protected
  149. * mode, so the unwinding is done directly from EL1. This removes
  150. * the need for shared buffers between host and hypervisor for
  151. * the stacktrace.
  152. */
  153. static void hyp_dump_backtrace(unsigned long hyp_offset)
  154. {
  155. struct kvm_nvhe_stacktrace_info *stacktrace_info;
  156. struct stack_info stacks[] = {
  157. stackinfo_get_overflow_kern_va(),
  158. stackinfo_get_hyp_kern_va(),
  159. };
  160. struct unwind_state state = {
  161. .stacks = stacks,
  162. .nr_stacks = ARRAY_SIZE(stacks),
  163. };
  164. stacktrace_info = this_cpu_ptr_nvhe_sym(kvm_stacktrace_info);
  165. kvm_nvhe_unwind_init(&state, stacktrace_info->fp, stacktrace_info->pc);
  166. kvm_nvhe_dump_backtrace_start();
  167. unwind(&state, kvm_nvhe_dump_backtrace_entry, (void *)hyp_offset);
  168. kvm_nvhe_dump_backtrace_end();
  169. }
  170. #ifdef CONFIG_PROTECTED_NVHE_STACKTRACE
  171. DECLARE_KVM_NVHE_PER_CPU(unsigned long [NVHE_STACKTRACE_SIZE/sizeof(long)],
  172. pkvm_stacktrace);
  173. /*
  174. * pkvm_dump_backtrace - Dump the protected nVHE HYP backtrace.
  175. *
  176. * @hyp_offset: hypervisor offset, used for address translation.
  177. *
  178. * Dumping of the pKVM HYP backtrace is done by reading the
  179. * stack addresses from the shared stacktrace buffer, since the
  180. * host cannot directly access hypervisor memory in protected
  181. * mode.
  182. */
  183. static void pkvm_dump_backtrace(unsigned long hyp_offset)
  184. {
  185. unsigned long *stacktrace
  186. = (unsigned long *) this_cpu_ptr_nvhe_sym(pkvm_stacktrace);
  187. int i;
  188. kvm_nvhe_dump_backtrace_start();
  189. /* The saved stacktrace is terminated by a null entry */
  190. for (i = 0;
  191. i < ARRAY_SIZE(kvm_nvhe_sym(pkvm_stacktrace)) && stacktrace[i];
  192. i++)
  193. kvm_nvhe_dump_backtrace_entry((void *)hyp_offset, stacktrace[i]);
  194. kvm_nvhe_dump_backtrace_end();
  195. }
  196. #else /* !CONFIG_PROTECTED_NVHE_STACKTRACE */
  197. static void pkvm_dump_backtrace(unsigned long hyp_offset)
  198. {
  199. kvm_err("Cannot dump pKVM nVHE stacktrace: !CONFIG_PROTECTED_NVHE_STACKTRACE\n");
  200. }
  201. #endif /* CONFIG_PROTECTED_NVHE_STACKTRACE */
  202. /*
  203. * kvm_nvhe_dump_backtrace - Dump KVM nVHE hypervisor backtrace.
  204. *
  205. * @hyp_offset: hypervisor offset, used for address translation.
  206. */
  207. void kvm_nvhe_dump_backtrace(unsigned long hyp_offset)
  208. {
  209. if (is_protected_kvm_enabled())
  210. pkvm_dump_backtrace(hyp_offset);
  211. else
  212. hyp_dump_backtrace(hyp_offset);
  213. }