crash.c 6.3 KB

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