crash.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * arch/ia64/kernel/crash.c
  4. *
  5. * Architecture specific (ia64) functions for kexec based crash dumps.
  6. *
  7. * Created by: Khalid Aziz <[email protected]>
  8. * Copyright (C) 2005 Hewlett-Packard Development Company, L.P.
  9. * Copyright (C) 2005 Intel Corp Zou Nan hai <[email protected]>
  10. *
  11. */
  12. #include <linux/smp.h>
  13. #include <linux/delay.h>
  14. #include <linux/crash_dump.h>
  15. #include <linux/memblock.h>
  16. #include <linux/kexec.h>
  17. #include <linux/elfcore.h>
  18. #include <linux/reboot.h>
  19. #include <linux/sysctl.h>
  20. #include <linux/init.h>
  21. #include <linux/kdebug.h>
  22. #include <asm/mca.h>
  23. int kdump_status[NR_CPUS];
  24. static atomic_t kdump_cpu_frozen;
  25. atomic_t kdump_in_progress;
  26. static int kdump_freeze_monarch;
  27. static int kdump_on_init = 1;
  28. static int kdump_on_fatal_mca = 1;
  29. extern void ia64_dump_cpu_regs(void *);
  30. static DEFINE_PER_CPU(struct elf_prstatus, elf_prstatus);
  31. void
  32. crash_save_this_cpu(void)
  33. {
  34. void *buf;
  35. unsigned long cfm, sof, sol;
  36. int cpu = smp_processor_id();
  37. struct elf_prstatus *prstatus = &per_cpu(elf_prstatus, cpu);
  38. elf_greg_t *dst = (elf_greg_t *)&(prstatus->pr_reg);
  39. memset(prstatus, 0, sizeof(*prstatus));
  40. prstatus->common.pr_pid = current->pid;
  41. ia64_dump_cpu_regs(dst);
  42. cfm = dst[43];
  43. sol = (cfm >> 7) & 0x7f;
  44. sof = cfm & 0x7f;
  45. dst[46] = (unsigned long)ia64_rse_skip_regs((unsigned long *)dst[46],
  46. sof - sol);
  47. buf = (u64 *) per_cpu_ptr(crash_notes, cpu);
  48. if (!buf)
  49. return;
  50. buf = append_elf_note(buf, KEXEC_CORE_NOTE_NAME, NT_PRSTATUS, prstatus,
  51. sizeof(*prstatus));
  52. final_note(buf);
  53. }
  54. #ifdef CONFIG_SMP
  55. static int
  56. kdump_wait_cpu_freeze(void)
  57. {
  58. int cpu_num = num_online_cpus() - 1;
  59. int timeout = 1000;
  60. while(timeout-- > 0) {
  61. if (atomic_read(&kdump_cpu_frozen) == cpu_num)
  62. return 0;
  63. udelay(1000);
  64. }
  65. return 1;
  66. }
  67. #endif
  68. void
  69. machine_crash_shutdown(struct pt_regs *pt)
  70. {
  71. /* This function is only called after the system
  72. * has paniced or is otherwise in a critical state.
  73. * The minimum amount of code to allow a kexec'd kernel
  74. * to run successfully needs to happen here.
  75. *
  76. * In practice this means shooting down the other cpus in
  77. * an SMP system.
  78. */
  79. kexec_disable_iosapic();
  80. #ifdef CONFIG_SMP
  81. /*
  82. * If kdump_on_init is set and an INIT is asserted here, kdump will
  83. * be started again via INIT monarch.
  84. */
  85. local_irq_disable();
  86. ia64_set_psr_mc(); /* mask MCA/INIT */
  87. if (atomic_inc_return(&kdump_in_progress) != 1)
  88. unw_init_running(kdump_cpu_freeze, NULL);
  89. /*
  90. * Now this cpu is ready for kdump.
  91. * Stop all others by IPI or INIT. They could receive INIT from
  92. * outside and might be INIT monarch, but only thing they have to
  93. * do is falling into kdump_cpu_freeze().
  94. *
  95. * If an INIT is asserted here:
  96. * - All receivers might be slaves, since some of cpus could already
  97. * be frozen and INIT might be masked on monarch. In this case,
  98. * all slaves will be frozen soon since kdump_in_progress will let
  99. * them into DIE_INIT_SLAVE_LEAVE.
  100. * - One might be a monarch, but INIT rendezvous will fail since
  101. * at least this cpu already have INIT masked so it never join
  102. * to the rendezvous. In this case, all slaves and monarch will
  103. * be frozen soon with no wait since the INIT rendezvous is skipped
  104. * by kdump_in_progress.
  105. */
  106. kdump_smp_send_stop();
  107. /* not all cpu response to IPI, send INIT to freeze them */
  108. if (kdump_wait_cpu_freeze()) {
  109. kdump_smp_send_init();
  110. /* wait again, don't go ahead if possible */
  111. kdump_wait_cpu_freeze();
  112. }
  113. #endif
  114. }
  115. static void
  116. machine_kdump_on_init(void)
  117. {
  118. crash_save_vmcoreinfo();
  119. local_irq_disable();
  120. kexec_disable_iosapic();
  121. machine_kexec(ia64_kimage);
  122. }
  123. void
  124. kdump_cpu_freeze(struct unw_frame_info *info, void *arg)
  125. {
  126. int cpuid;
  127. local_irq_disable();
  128. cpuid = smp_processor_id();
  129. crash_save_this_cpu();
  130. current->thread.ksp = (__u64)info->sw - 16;
  131. ia64_set_psr_mc(); /* mask MCA/INIT and stop reentrance */
  132. atomic_inc(&kdump_cpu_frozen);
  133. kdump_status[cpuid] = 1;
  134. mb();
  135. for (;;)
  136. cpu_relax();
  137. }
  138. static int
  139. kdump_init_notifier(struct notifier_block *self, unsigned long val, void *data)
  140. {
  141. struct ia64_mca_notify_die *nd;
  142. struct die_args *args = data;
  143. if (atomic_read(&kdump_in_progress)) {
  144. switch (val) {
  145. case DIE_INIT_MONARCH_LEAVE:
  146. if (!kdump_freeze_monarch)
  147. break;
  148. fallthrough;
  149. case DIE_INIT_SLAVE_LEAVE:
  150. case DIE_INIT_MONARCH_ENTER:
  151. case DIE_MCA_RENDZVOUS_LEAVE:
  152. unw_init_running(kdump_cpu_freeze, NULL);
  153. break;
  154. }
  155. }
  156. if (!kdump_on_init && !kdump_on_fatal_mca)
  157. return NOTIFY_DONE;
  158. if (!ia64_kimage) {
  159. if (val == DIE_INIT_MONARCH_LEAVE)
  160. ia64_mca_printk(KERN_NOTICE
  161. "%s: kdump not configured\n",
  162. __func__);
  163. return NOTIFY_DONE;
  164. }
  165. if (val != DIE_INIT_MONARCH_LEAVE &&
  166. val != DIE_INIT_MONARCH_PROCESS &&
  167. val != DIE_MCA_MONARCH_LEAVE)
  168. return NOTIFY_DONE;
  169. nd = (struct ia64_mca_notify_die *)args->err;
  170. switch (val) {
  171. case DIE_INIT_MONARCH_PROCESS:
  172. /* Reason code 1 means machine check rendezvous*/
  173. if (kdump_on_init && (nd->sos->rv_rc != 1)) {
  174. if (atomic_inc_return(&kdump_in_progress) != 1)
  175. kdump_freeze_monarch = 1;
  176. }
  177. break;
  178. case DIE_INIT_MONARCH_LEAVE:
  179. /* Reason code 1 means machine check rendezvous*/
  180. if (kdump_on_init && (nd->sos->rv_rc != 1))
  181. machine_kdump_on_init();
  182. break;
  183. case DIE_MCA_MONARCH_LEAVE:
  184. /* *(nd->data) indicate if MCA is recoverable */
  185. if (kdump_on_fatal_mca && !(*(nd->data))) {
  186. if (atomic_inc_return(&kdump_in_progress) == 1)
  187. machine_kdump_on_init();
  188. /* We got fatal MCA while kdump!? No way!! */
  189. }
  190. break;
  191. }
  192. return NOTIFY_DONE;
  193. }
  194. #ifdef CONFIG_SYSCTL
  195. static struct ctl_table kdump_ctl_table[] = {
  196. {
  197. .procname = "kdump_on_init",
  198. .data = &kdump_on_init,
  199. .maxlen = sizeof(int),
  200. .mode = 0644,
  201. .proc_handler = proc_dointvec,
  202. },
  203. {
  204. .procname = "kdump_on_fatal_mca",
  205. .data = &kdump_on_fatal_mca,
  206. .maxlen = sizeof(int),
  207. .mode = 0644,
  208. .proc_handler = proc_dointvec,
  209. },
  210. { }
  211. };
  212. static struct ctl_table sys_table[] = {
  213. {
  214. .procname = "kernel",
  215. .mode = 0555,
  216. .child = kdump_ctl_table,
  217. },
  218. { }
  219. };
  220. #endif
  221. static int
  222. machine_crash_setup(void)
  223. {
  224. /* be notified before default_monarch_init_process */
  225. static struct notifier_block kdump_init_notifier_nb = {
  226. .notifier_call = kdump_init_notifier,
  227. .priority = 1,
  228. };
  229. int ret;
  230. if((ret = register_die_notifier(&kdump_init_notifier_nb)) != 0)
  231. return ret;
  232. #ifdef CONFIG_SYSCTL
  233. register_sysctl_table(sys_table);
  234. #endif
  235. return 0;
  236. }
  237. __initcall(machine_crash_setup);