crash_dump.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. /*
  2. * S390 kdump implementation
  3. *
  4. * Copyright IBM Corp. 2011
  5. * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com>
  6. */
  7. #include <linux/crash_dump.h>
  8. #include <asm/lowcore.h>
  9. #include <linux/kernel.h>
  10. #include <linux/module.h>
  11. #include <linux/gfp.h>
  12. #include <linux/slab.h>
  13. #include <linux/bootmem.h>
  14. #include <linux/elf.h>
  15. #include <asm/os_info.h>
  16. #include <asm/elf.h>
  17. #include <asm/ipl.h>
  18. #define PTR_ADD(x, y) (((char *) (x)) + ((unsigned long) (y)))
  19. #define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y)))
  20. #define PTR_DIFF(x, y) ((unsigned long)(((char *) (x)) - ((unsigned long) (y))))
  21. /*
  22. * Return physical address for virtual address
  23. */
  24. static inline void *load_real_addr(void *addr)
  25. {
  26. unsigned long real_addr;
  27. asm volatile(
  28. " lra %0,0(%1)\n"
  29. " jz 0f\n"
  30. " la %0,0\n"
  31. "0:"
  32. : "=a" (real_addr) : "a" (addr) : "cc");
  33. return (void *)real_addr;
  34. }
  35. /*
  36. * Copy up to one page to vmalloc or real memory
  37. */
  38. static ssize_t copy_page_real(void *buf, void *src, size_t csize)
  39. {
  40. size_t size;
  41. if (is_vmalloc_addr(buf)) {
  42. BUG_ON(csize >= PAGE_SIZE);
  43. /* If buf is not page aligned, copy first part */
  44. size = min(roundup(__pa(buf), PAGE_SIZE) - __pa(buf), csize);
  45. if (size) {
  46. if (memcpy_real(load_real_addr(buf), src, size))
  47. return -EFAULT;
  48. buf += size;
  49. src += size;
  50. }
  51. /* Copy second part */
  52. size = csize - size;
  53. return (size) ? memcpy_real(load_real_addr(buf), src, size) : 0;
  54. } else {
  55. return memcpy_real(buf, src, csize);
  56. }
  57. }
  58. /*
  59. * Pointer to ELF header in new kernel
  60. */
  61. static void *elfcorehdr_newmem;
  62. /*
  63. * Copy one page from "oldmem"
  64. *
  65. * For the kdump reserved memory this functions performs a swap operation:
  66. * - [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE] is mapped to [0 - OLDMEM_SIZE].
  67. * - [0 - OLDMEM_SIZE] is mapped to [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE]
  68. */
  69. ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
  70. size_t csize, unsigned long offset, int userbuf)
  71. {
  72. unsigned long src;
  73. int rc;
  74. if (!csize)
  75. return 0;
  76. src = (pfn << PAGE_SHIFT) + offset;
  77. if (src < OLDMEM_SIZE)
  78. src += OLDMEM_BASE;
  79. else if (src > OLDMEM_BASE &&
  80. src < OLDMEM_BASE + OLDMEM_SIZE)
  81. src -= OLDMEM_BASE;
  82. if (userbuf)
  83. rc = copy_to_user_real((void __force __user *) buf,
  84. (void *) src, csize);
  85. else
  86. rc = copy_page_real(buf, (void *) src, csize);
  87. return (rc == 0) ? csize : rc;
  88. }
  89. /*
  90. * Remap "oldmem"
  91. *
  92. * For the kdump reserved memory this functions performs a swap operation:
  93. * [0 - OLDMEM_SIZE] is mapped to [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE]
  94. */
  95. int remap_oldmem_pfn_range(struct vm_area_struct *vma, unsigned long from,
  96. unsigned long pfn, unsigned long size, pgprot_t prot)
  97. {
  98. unsigned long size_old;
  99. int rc;
  100. if (pfn < OLDMEM_SIZE >> PAGE_SHIFT) {
  101. size_old = min(size, OLDMEM_SIZE - (pfn << PAGE_SHIFT));
  102. rc = remap_pfn_range(vma, from,
  103. pfn + (OLDMEM_BASE >> PAGE_SHIFT),
  104. size_old, prot);
  105. if (rc || size == size_old)
  106. return rc;
  107. size -= size_old;
  108. from += size_old;
  109. pfn += size_old >> PAGE_SHIFT;
  110. }
  111. return remap_pfn_range(vma, from, pfn, size, prot);
  112. }
  113. /*
  114. * Copy memory from old kernel
  115. */
  116. int copy_from_oldmem(void *dest, void *src, size_t count)
  117. {
  118. unsigned long copied = 0;
  119. int rc;
  120. if ((unsigned long) src < OLDMEM_SIZE) {
  121. copied = min(count, OLDMEM_SIZE - (unsigned long) src);
  122. rc = memcpy_real(dest, src + OLDMEM_BASE, copied);
  123. if (rc)
  124. return rc;
  125. }
  126. return memcpy_real(dest + copied, src + copied, count - copied);
  127. }
  128. /*
  129. * Alloc memory and panic in case of ENOMEM
  130. */
  131. static void *kzalloc_panic(int len)
  132. {
  133. void *rc;
  134. rc = kzalloc(len, GFP_KERNEL);
  135. if (!rc)
  136. panic("s390 kdump kzalloc (%d) failed", len);
  137. return rc;
  138. }
  139. /*
  140. * Get memory layout and create hole for oldmem
  141. */
  142. static struct mem_chunk *get_memory_layout(void)
  143. {
  144. struct mem_chunk *chunk_array;
  145. chunk_array = kzalloc_panic(MEMORY_CHUNKS * sizeof(struct mem_chunk));
  146. detect_memory_layout(chunk_array, 0);
  147. create_mem_hole(chunk_array, OLDMEM_BASE, OLDMEM_SIZE);
  148. return chunk_array;
  149. }
  150. /*
  151. * Initialize ELF note
  152. */
  153. static void *nt_init(void *buf, Elf64_Word type, void *desc, int d_len,
  154. const char *name)
  155. {
  156. Elf64_Nhdr *note;
  157. u64 len;
  158. note = (Elf64_Nhdr *)buf;
  159. note->n_namesz = strlen(name) + 1;
  160. note->n_descsz = d_len;
  161. note->n_type = type;
  162. len = sizeof(Elf64_Nhdr);
  163. memcpy(buf + len, name, note->n_namesz);
  164. len = roundup(len + note->n_namesz, 4);
  165. memcpy(buf + len, desc, note->n_descsz);
  166. len = roundup(len + note->n_descsz, 4);
  167. return PTR_ADD(buf, len);
  168. }
  169. /*
  170. * Initialize prstatus note
  171. */
  172. static void *nt_prstatus(void *ptr, struct save_area *sa)
  173. {
  174. struct elf_prstatus nt_prstatus;
  175. static int cpu_nr = 1;
  176. memset(&nt_prstatus, 0, sizeof(nt_prstatus));
  177. memcpy(&nt_prstatus.pr_reg.gprs, sa->gp_regs, sizeof(sa->gp_regs));
  178. memcpy(&nt_prstatus.pr_reg.psw, sa->psw, sizeof(sa->psw));
  179. memcpy(&nt_prstatus.pr_reg.acrs, sa->acc_regs, sizeof(sa->acc_regs));
  180. nt_prstatus.pr_pid = cpu_nr;
  181. cpu_nr++;
  182. return nt_init(ptr, NT_PRSTATUS, &nt_prstatus, sizeof(nt_prstatus),
  183. "CORE");
  184. }
  185. /*
  186. * Initialize fpregset (floating point) note
  187. */
  188. static void *nt_fpregset(void *ptr, struct save_area *sa)
  189. {
  190. elf_fpregset_t nt_fpregset;
  191. memset(&nt_fpregset, 0, sizeof(nt_fpregset));
  192. memcpy(&nt_fpregset.fpc, &sa->fp_ctrl_reg, sizeof(sa->fp_ctrl_reg));
  193. memcpy(&nt_fpregset.fprs, &sa->fp_regs, sizeof(sa->fp_regs));
  194. return nt_init(ptr, NT_PRFPREG, &nt_fpregset, sizeof(nt_fpregset),
  195. "CORE");
  196. }
  197. /*
  198. * Initialize timer note
  199. */
  200. static void *nt_s390_timer(void *ptr, struct save_area *sa)
  201. {
  202. return nt_init(ptr, NT_S390_TIMER, &sa->timer, sizeof(sa->timer),
  203. KEXEC_CORE_NOTE_NAME);
  204. }
  205. /*
  206. * Initialize TOD clock comparator note
  207. */
  208. static void *nt_s390_tod_cmp(void *ptr, struct save_area *sa)
  209. {
  210. return nt_init(ptr, NT_S390_TODCMP, &sa->clk_cmp,
  211. sizeof(sa->clk_cmp), KEXEC_CORE_NOTE_NAME);
  212. }
  213. /*
  214. * Initialize TOD programmable register note
  215. */
  216. static void *nt_s390_tod_preg(void *ptr, struct save_area *sa)
  217. {
  218. return nt_init(ptr, NT_S390_TODPREG, &sa->tod_reg,
  219. sizeof(sa->tod_reg), KEXEC_CORE_NOTE_NAME);
  220. }
  221. /*
  222. * Initialize control register note
  223. */
  224. static void *nt_s390_ctrs(void *ptr, struct save_area *sa)
  225. {
  226. return nt_init(ptr, NT_S390_CTRS, &sa->ctrl_regs,
  227. sizeof(sa->ctrl_regs), KEXEC_CORE_NOTE_NAME);
  228. }
  229. /*
  230. * Initialize prefix register note
  231. */
  232. static void *nt_s390_prefix(void *ptr, struct save_area *sa)
  233. {
  234. return nt_init(ptr, NT_S390_PREFIX, &sa->pref_reg,
  235. sizeof(sa->pref_reg), KEXEC_CORE_NOTE_NAME);
  236. }
  237. /*
  238. * Fill ELF notes for one CPU with save area registers
  239. */
  240. void *fill_cpu_elf_notes(void *ptr, struct save_area *sa)
  241. {
  242. ptr = nt_prstatus(ptr, sa);
  243. ptr = nt_fpregset(ptr, sa);
  244. ptr = nt_s390_timer(ptr, sa);
  245. ptr = nt_s390_tod_cmp(ptr, sa);
  246. ptr = nt_s390_tod_preg(ptr, sa);
  247. ptr = nt_s390_ctrs(ptr, sa);
  248. ptr = nt_s390_prefix(ptr, sa);
  249. return ptr;
  250. }
  251. /*
  252. * Initialize prpsinfo note (new kernel)
  253. */
  254. static void *nt_prpsinfo(void *ptr)
  255. {
  256. struct elf_prpsinfo prpsinfo;
  257. memset(&prpsinfo, 0, sizeof(prpsinfo));
  258. prpsinfo.pr_sname = 'R';
  259. strcpy(prpsinfo.pr_fname, "vmlinux");
  260. return nt_init(ptr, NT_PRPSINFO, &prpsinfo, sizeof(prpsinfo),
  261. KEXEC_CORE_NOTE_NAME);
  262. }
  263. /*
  264. * Get vmcoreinfo using lowcore->vmcore_info (new kernel)
  265. */
  266. static void *get_vmcoreinfo_old(unsigned long *size)
  267. {
  268. char nt_name[11], *vmcoreinfo;
  269. Elf64_Nhdr note;
  270. void *addr;
  271. if (copy_from_oldmem(&addr, &S390_lowcore.vmcore_info, sizeof(addr)))
  272. return NULL;
  273. memset(nt_name, 0, sizeof(nt_name));
  274. if (copy_from_oldmem(&note, addr, sizeof(note)))
  275. return NULL;
  276. if (copy_from_oldmem(nt_name, addr + sizeof(note), sizeof(nt_name) - 1))
  277. return NULL;
  278. if (strcmp(nt_name, "VMCOREINFO") != 0)
  279. return NULL;
  280. vmcoreinfo = kzalloc_panic(note.n_descsz);
  281. if (copy_from_oldmem(vmcoreinfo, addr + 24, note.n_descsz))
  282. return NULL;
  283. *size = note.n_descsz;
  284. return vmcoreinfo;
  285. }
  286. /*
  287. * Initialize vmcoreinfo note (new kernel)
  288. */
  289. static void *nt_vmcoreinfo(void *ptr)
  290. {
  291. unsigned long size;
  292. void *vmcoreinfo;
  293. vmcoreinfo = os_info_old_entry(OS_INFO_VMCOREINFO, &size);
  294. if (!vmcoreinfo)
  295. vmcoreinfo = get_vmcoreinfo_old(&size);
  296. if (!vmcoreinfo)
  297. return ptr;
  298. return nt_init(ptr, 0, vmcoreinfo, size, "VMCOREINFO");
  299. }
  300. /*
  301. * Initialize ELF header (new kernel)
  302. */
  303. static void *ehdr_init(Elf64_Ehdr *ehdr, int mem_chunk_cnt)
  304. {
  305. memset(ehdr, 0, sizeof(*ehdr));
  306. memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
  307. ehdr->e_ident[EI_CLASS] = ELFCLASS64;
  308. ehdr->e_ident[EI_DATA] = ELFDATA2MSB;
  309. ehdr->e_ident[EI_VERSION] = EV_CURRENT;
  310. memset(ehdr->e_ident + EI_PAD, 0, EI_NIDENT - EI_PAD);
  311. ehdr->e_type = ET_CORE;
  312. ehdr->e_machine = EM_S390;
  313. ehdr->e_version = EV_CURRENT;
  314. ehdr->e_phoff = sizeof(Elf64_Ehdr);
  315. ehdr->e_ehsize = sizeof(Elf64_Ehdr);
  316. ehdr->e_phentsize = sizeof(Elf64_Phdr);
  317. ehdr->e_phnum = mem_chunk_cnt + 1;
  318. return ehdr + 1;
  319. }
  320. /*
  321. * Return CPU count for ELF header (new kernel)
  322. */
  323. static int get_cpu_cnt(void)
  324. {
  325. int i, cpus = 0;
  326. for (i = 0; zfcpdump_save_areas[i]; i++) {
  327. if (zfcpdump_save_areas[i]->pref_reg == 0)
  328. continue;
  329. cpus++;
  330. }
  331. return cpus;
  332. }
  333. /*
  334. * Return memory chunk count for ELF header (new kernel)
  335. */
  336. static int get_mem_chunk_cnt(void)
  337. {
  338. struct mem_chunk *chunk_array, *mem_chunk;
  339. int i, cnt = 0;
  340. chunk_array = get_memory_layout();
  341. for (i = 0; i < MEMORY_CHUNKS; i++) {
  342. mem_chunk = &chunk_array[i];
  343. if (chunk_array[i].type != CHUNK_READ_WRITE &&
  344. chunk_array[i].type != CHUNK_READ_ONLY)
  345. continue;
  346. if (mem_chunk->size == 0)
  347. continue;
  348. cnt++;
  349. }
  350. kfree(chunk_array);
  351. return cnt;
  352. }
  353. /*
  354. * Initialize ELF loads (new kernel)
  355. */
  356. static int loads_init(Elf64_Phdr *phdr, u64 loads_offset)
  357. {
  358. struct mem_chunk *chunk_array, *mem_chunk;
  359. int i;
  360. chunk_array = get_memory_layout();
  361. for (i = 0; i < MEMORY_CHUNKS; i++) {
  362. mem_chunk = &chunk_array[i];
  363. if (mem_chunk->size == 0)
  364. continue;
  365. if (chunk_array[i].type != CHUNK_READ_WRITE &&
  366. chunk_array[i].type != CHUNK_READ_ONLY)
  367. continue;
  368. else
  369. phdr->p_filesz = mem_chunk->size;
  370. phdr->p_type = PT_LOAD;
  371. phdr->p_offset = mem_chunk->addr;
  372. phdr->p_vaddr = mem_chunk->addr;
  373. phdr->p_paddr = mem_chunk->addr;
  374. phdr->p_memsz = mem_chunk->size;
  375. phdr->p_flags = PF_R | PF_W | PF_X;
  376. phdr->p_align = PAGE_SIZE;
  377. phdr++;
  378. }
  379. kfree(chunk_array);
  380. return i;
  381. }
  382. /*
  383. * Initialize notes (new kernel)
  384. */
  385. static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)
  386. {
  387. struct save_area *sa;
  388. void *ptr_start = ptr;
  389. int i;
  390. ptr = nt_prpsinfo(ptr);
  391. for (i = 0; zfcpdump_save_areas[i]; i++) {
  392. sa = zfcpdump_save_areas[i];
  393. if (sa->pref_reg == 0)
  394. continue;
  395. ptr = fill_cpu_elf_notes(ptr, sa);
  396. }
  397. ptr = nt_vmcoreinfo(ptr);
  398. memset(phdr, 0, sizeof(*phdr));
  399. phdr->p_type = PT_NOTE;
  400. phdr->p_offset = notes_offset;
  401. phdr->p_filesz = (unsigned long) PTR_SUB(ptr, ptr_start);
  402. phdr->p_memsz = phdr->p_filesz;
  403. return ptr;
  404. }
  405. /*
  406. * Create ELF core header (new kernel)
  407. */
  408. int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size)
  409. {
  410. Elf64_Phdr *phdr_notes, *phdr_loads;
  411. int mem_chunk_cnt;
  412. void *ptr, *hdr;
  413. u32 alloc_size;
  414. u64 hdr_off;
  415. if (!OLDMEM_BASE)
  416. return 0;
  417. /* If elfcorehdr= has been passed via cmdline, we use that one */
  418. if (elfcorehdr_addr != ELFCORE_ADDR_MAX)
  419. return 0;
  420. mem_chunk_cnt = get_mem_chunk_cnt();
  421. alloc_size = 0x1000 + get_cpu_cnt() * 0x300 +
  422. mem_chunk_cnt * sizeof(Elf64_Phdr);
  423. hdr = kzalloc_panic(alloc_size);
  424. /* Init elf header */
  425. ptr = ehdr_init(hdr, mem_chunk_cnt);
  426. /* Init program headers */
  427. phdr_notes = ptr;
  428. ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr));
  429. phdr_loads = ptr;
  430. ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr) * mem_chunk_cnt);
  431. /* Init notes */
  432. hdr_off = PTR_DIFF(ptr, hdr);
  433. ptr = notes_init(phdr_notes, ptr, ((unsigned long) hdr) + hdr_off);
  434. /* Init loads */
  435. hdr_off = PTR_DIFF(ptr, hdr);
  436. loads_init(phdr_loads, hdr_off);
  437. *addr = (unsigned long long) hdr;
  438. elfcorehdr_newmem = hdr;
  439. *size = (unsigned long long) hdr_off;
  440. BUG_ON(elfcorehdr_size > alloc_size);
  441. return 0;
  442. }
  443. /*
  444. * Free ELF core header (new kernel)
  445. */
  446. void elfcorehdr_free(unsigned long long addr)
  447. {
  448. if (!elfcorehdr_newmem)
  449. return;
  450. kfree((void *)(unsigned long)addr);
  451. }
  452. /*
  453. * Read from ELF header
  454. */
  455. ssize_t elfcorehdr_read(char *buf, size_t count, u64 *ppos)
  456. {
  457. void *src = (void *)(unsigned long)*ppos;
  458. src = elfcorehdr_newmem ? src : src - OLDMEM_BASE;
  459. memcpy(buf, src, count);
  460. *ppos += count;
  461. return count;
  462. }
  463. /*
  464. * Read from ELF notes data
  465. */
  466. ssize_t elfcorehdr_read_notes(char *buf, size_t count, u64 *ppos)
  467. {
  468. void *src = (void *)(unsigned long)*ppos;
  469. int rc;
  470. if (elfcorehdr_newmem) {
  471. memcpy(buf, src, count);
  472. } else {
  473. rc = copy_from_oldmem(buf, src, count);
  474. if (rc)
  475. return rc;
  476. }
  477. *ppos += count;
  478. return count;
  479. }