crash_dump.c 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. /*
  2. * Routines for doing kexec-based kdump.
  3. *
  4. * Copyright (C) 2005, IBM Corp.
  5. *
  6. * Created by: Michael Ellerman
  7. *
  8. * This source code is licensed under the GNU General Public License,
  9. * Version 2. See the file COPYING for more details.
  10. */
  11. #undef DEBUG
  12. #include <linux/crash_dump.h>
  13. #include <linux/bootmem.h>
  14. #include <asm/kdump.h>
  15. #include <asm/lmb.h>
  16. #include <asm/firmware.h>
  17. #ifdef DEBUG
  18. #include <asm/udbg.h>
  19. #define DBG(fmt...) udbg_printf(fmt)
  20. #else
  21. #define DBG(fmt...)
  22. #endif
  23. static void __init create_trampoline(unsigned long addr)
  24. {
  25. /* The maximum range of a single instruction branch, is the current
  26. * instruction's address + (32 MB - 4) bytes. For the trampoline we
  27. * need to branch to current address + 32 MB. So we insert a nop at
  28. * the trampoline address, then the next instruction (+ 4 bytes)
  29. * does a branch to (32 MB - 4). The net effect is that when we
  30. * branch to "addr" we jump to ("addr" + 32 MB). Although it requires
  31. * two instructions it doesn't require any registers.
  32. */
  33. create_instruction(addr, 0x60000000); /* nop */
  34. create_branch(addr + 4, addr + PHYSICAL_START, 0);
  35. }
  36. void __init kdump_setup(void)
  37. {
  38. unsigned long i;
  39. DBG(" -> kdump_setup()\n");
  40. for (i = KDUMP_TRAMPOLINE_START; i < KDUMP_TRAMPOLINE_END; i += 8) {
  41. create_trampoline(i);
  42. }
  43. create_trampoline(__pa(system_reset_fwnmi) - PHYSICAL_START);
  44. create_trampoline(__pa(machine_check_fwnmi) - PHYSICAL_START);
  45. DBG(" <- kdump_setup()\n");
  46. }
  47. static int __init parse_elfcorehdr(char *p)
  48. {
  49. if (p)
  50. elfcorehdr_addr = memparse(p, &p);
  51. return 0;
  52. }
  53. __setup("elfcorehdr=", parse_elfcorehdr);
  54. static int __init parse_savemaxmem(char *p)
  55. {
  56. if (p)
  57. saved_max_pfn = (memparse(p, &p) >> PAGE_SHIFT) - 1;
  58. return 0;
  59. }
  60. __setup("savemaxmem=", parse_savemaxmem);