2 * S390 kdump implementation
4 * Copyright IBM Corp. 2011
5 * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com>
8 #include <linux/crash_dump.h>
9 #include <asm/lowcore.h>
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/gfp.h>
13 #include <linux/slab.h>
14 #include <linux/bootmem.h>
15 #include <linux/elf.h>
16 #include <asm/os_info.h>
21 #define PTR_ADD(x, y) (((char *) (x)) + ((unsigned long) (y)))
22 #define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y)))
23 #define PTR_DIFF(x, y) ((unsigned long)(((char *) (x)) - ((unsigned long) (y))))
27 * Return physical address for virtual address
29 static inline void *load_real_addr(void *addr
)
31 unsigned long real_addr
;
38 : "=a" (real_addr
) : "a" (addr
) : "cc");
39 return (void *)real_addr
;
43 * Copy real to virtual or real memory
45 static int copy_from_realmem(void *dest
, void *src
, size_t count
)
52 if (!is_vmalloc_or_module_addr(dest
))
53 return memcpy_real(dest
, src
, count
);
55 size
= min(count
, PAGE_SIZE
- (__pa(dest
) & ~PAGE_MASK
));
56 if (memcpy_real(load_real_addr(dest
), src
, size
))
66 * Pointer to ELF header in new kernel
68 static void *elfcorehdr_newmem
;
71 * Copy one page from zfcpdump "oldmem"
73 * For pages below ZFCPDUMP_HSA_SIZE memory from the HSA is copied. Otherwise
74 * real memory copy is used.
76 static ssize_t
copy_oldmem_page_zfcpdump(char *buf
, size_t csize
,
77 unsigned long src
, int userbuf
)
81 if (src
< ZFCPDUMP_HSA_SIZE
) {
82 rc
= memcpy_hsa(buf
, src
, csize
, userbuf
);
85 rc
= copy_to_user_real((void __force __user
*) buf
,
88 rc
= memcpy_real(buf
, (void *) src
, csize
);
90 return rc
? rc
: csize
;
94 * Copy one page from kdump "oldmem"
96 * For the kdump reserved memory this functions performs a swap operation:
97 * - [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE] is mapped to [0 - OLDMEM_SIZE].
98 * - [0 - OLDMEM_SIZE] is mapped to [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE]
100 static ssize_t
copy_oldmem_page_kdump(char *buf
, size_t csize
,
101 unsigned long src
, int userbuf
)
106 if (src
< OLDMEM_SIZE
)
108 else if (src
> OLDMEM_BASE
&&
109 src
< OLDMEM_BASE
+ OLDMEM_SIZE
)
112 rc
= copy_to_user_real((void __force __user
*) buf
,
113 (void *) src
, csize
);
115 rc
= copy_from_realmem(buf
, (void *) src
, csize
);
116 return (rc
== 0) ? rc
: csize
;
120 * Copy one page from "oldmem"
122 ssize_t
copy_oldmem_page(unsigned long pfn
, char *buf
, size_t csize
,
123 unsigned long offset
, int userbuf
)
129 src
= (pfn
<< PAGE_SHIFT
) + offset
;
131 return copy_oldmem_page_kdump(buf
, csize
, src
, userbuf
);
133 return copy_oldmem_page_zfcpdump(buf
, csize
, src
, userbuf
);
137 * Remap "oldmem" for kdump
139 * For the kdump reserved memory this functions performs a swap operation:
140 * [0 - OLDMEM_SIZE] is mapped to [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE]
142 static int remap_oldmem_pfn_range_kdump(struct vm_area_struct
*vma
,
143 unsigned long from
, unsigned long pfn
,
144 unsigned long size
, pgprot_t prot
)
146 unsigned long size_old
;
149 if (pfn
< OLDMEM_SIZE
>> PAGE_SHIFT
) {
150 size_old
= min(size
, OLDMEM_SIZE
- (pfn
<< PAGE_SHIFT
));
151 rc
= remap_pfn_range(vma
, from
,
152 pfn
+ (OLDMEM_BASE
>> PAGE_SHIFT
),
154 if (rc
|| size
== size_old
)
158 pfn
+= size_old
>> PAGE_SHIFT
;
160 return remap_pfn_range(vma
, from
, pfn
, size
, prot
);
164 * Remap "oldmem" for zfcpdump
166 * We only map available memory above ZFCPDUMP_HSA_SIZE. Memory below
167 * ZFCPDUMP_HSA_SIZE is read on demand using the copy_oldmem_page() function.
169 static int remap_oldmem_pfn_range_zfcpdump(struct vm_area_struct
*vma
,
172 unsigned long size
, pgprot_t prot
)
174 unsigned long size_hsa
;
176 if (pfn
< ZFCPDUMP_HSA_SIZE
>> PAGE_SHIFT
) {
177 size_hsa
= min(size
, ZFCPDUMP_HSA_SIZE
- (pfn
<< PAGE_SHIFT
));
178 if (size
== size_hsa
)
182 pfn
+= size_hsa
>> PAGE_SHIFT
;
184 return remap_pfn_range(vma
, from
, pfn
, size
, prot
);
188 * Remap "oldmem" for kdump or zfcpdump
190 int remap_oldmem_pfn_range(struct vm_area_struct
*vma
, unsigned long from
,
191 unsigned long pfn
, unsigned long size
, pgprot_t prot
)
194 return remap_oldmem_pfn_range_kdump(vma
, from
, pfn
, size
, prot
);
196 return remap_oldmem_pfn_range_zfcpdump(vma
, from
, pfn
, size
,
201 * Copy memory from old kernel
203 int copy_from_oldmem(void *dest
, void *src
, size_t count
)
205 unsigned long copied
= 0;
209 if ((unsigned long) src
< OLDMEM_SIZE
) {
210 copied
= min(count
, OLDMEM_SIZE
- (unsigned long) src
);
211 rc
= copy_from_realmem(dest
, src
+ OLDMEM_BASE
, copied
);
216 if ((unsigned long) src
< ZFCPDUMP_HSA_SIZE
) {
218 ZFCPDUMP_HSA_SIZE
- (unsigned long) src
);
219 rc
= memcpy_hsa(dest
, (unsigned long) src
, copied
, 0);
224 return copy_from_realmem(dest
+ copied
, src
+ copied
, count
- copied
);
228 * Alloc memory and panic in case of ENOMEM
230 static void *kzalloc_panic(int len
)
234 rc
= kzalloc(len
, GFP_KERNEL
);
236 panic("s390 kdump kzalloc (%d) failed", len
);
241 * Get memory layout and create hole for oldmem
243 static struct mem_chunk
*get_memory_layout(void)
245 struct mem_chunk
*chunk_array
;
247 chunk_array
= kzalloc_panic(MEMORY_CHUNKS
* sizeof(struct mem_chunk
));
248 detect_memory_layout(chunk_array
, 0);
249 create_mem_hole(chunk_array
, OLDMEM_BASE
, OLDMEM_SIZE
);
254 * Initialize ELF note
256 static void *nt_init(void *buf
, Elf64_Word type
, void *desc
, int d_len
,
262 note
= (Elf64_Nhdr
*)buf
;
263 note
->n_namesz
= strlen(name
) + 1;
264 note
->n_descsz
= d_len
;
266 len
= sizeof(Elf64_Nhdr
);
268 memcpy(buf
+ len
, name
, note
->n_namesz
);
269 len
= roundup(len
+ note
->n_namesz
, 4);
271 memcpy(buf
+ len
, desc
, note
->n_descsz
);
272 len
= roundup(len
+ note
->n_descsz
, 4);
274 return PTR_ADD(buf
, len
);
278 * Initialize prstatus note
280 static void *nt_prstatus(void *ptr
, struct save_area
*sa
)
282 struct elf_prstatus nt_prstatus
;
283 static int cpu_nr
= 1;
285 memset(&nt_prstatus
, 0, sizeof(nt_prstatus
));
286 memcpy(&nt_prstatus
.pr_reg
.gprs
, sa
->gp_regs
, sizeof(sa
->gp_regs
));
287 memcpy(&nt_prstatus
.pr_reg
.psw
, sa
->psw
, sizeof(sa
->psw
));
288 memcpy(&nt_prstatus
.pr_reg
.acrs
, sa
->acc_regs
, sizeof(sa
->acc_regs
));
289 nt_prstatus
.pr_pid
= cpu_nr
;
292 return nt_init(ptr
, NT_PRSTATUS
, &nt_prstatus
, sizeof(nt_prstatus
),
297 * Initialize fpregset (floating point) note
299 static void *nt_fpregset(void *ptr
, struct save_area
*sa
)
301 elf_fpregset_t nt_fpregset
;
303 memset(&nt_fpregset
, 0, sizeof(nt_fpregset
));
304 memcpy(&nt_fpregset
.fpc
, &sa
->fp_ctrl_reg
, sizeof(sa
->fp_ctrl_reg
));
305 memcpy(&nt_fpregset
.fprs
, &sa
->fp_regs
, sizeof(sa
->fp_regs
));
307 return nt_init(ptr
, NT_PRFPREG
, &nt_fpregset
, sizeof(nt_fpregset
),
312 * Initialize timer note
314 static void *nt_s390_timer(void *ptr
, struct save_area
*sa
)
316 return nt_init(ptr
, NT_S390_TIMER
, &sa
->timer
, sizeof(sa
->timer
),
317 KEXEC_CORE_NOTE_NAME
);
321 * Initialize TOD clock comparator note
323 static void *nt_s390_tod_cmp(void *ptr
, struct save_area
*sa
)
325 return nt_init(ptr
, NT_S390_TODCMP
, &sa
->clk_cmp
,
326 sizeof(sa
->clk_cmp
), KEXEC_CORE_NOTE_NAME
);
330 * Initialize TOD programmable register note
332 static void *nt_s390_tod_preg(void *ptr
, struct save_area
*sa
)
334 return nt_init(ptr
, NT_S390_TODPREG
, &sa
->tod_reg
,
335 sizeof(sa
->tod_reg
), KEXEC_CORE_NOTE_NAME
);
339 * Initialize control register note
341 static void *nt_s390_ctrs(void *ptr
, struct save_area
*sa
)
343 return nt_init(ptr
, NT_S390_CTRS
, &sa
->ctrl_regs
,
344 sizeof(sa
->ctrl_regs
), KEXEC_CORE_NOTE_NAME
);
348 * Initialize prefix register note
350 static void *nt_s390_prefix(void *ptr
, struct save_area
*sa
)
352 return nt_init(ptr
, NT_S390_PREFIX
, &sa
->pref_reg
,
353 sizeof(sa
->pref_reg
), KEXEC_CORE_NOTE_NAME
);
357 * Fill ELF notes for one CPU with save area registers
359 void *fill_cpu_elf_notes(void *ptr
, struct save_area
*sa
)
361 ptr
= nt_prstatus(ptr
, sa
);
362 ptr
= nt_fpregset(ptr
, sa
);
363 ptr
= nt_s390_timer(ptr
, sa
);
364 ptr
= nt_s390_tod_cmp(ptr
, sa
);
365 ptr
= nt_s390_tod_preg(ptr
, sa
);
366 ptr
= nt_s390_ctrs(ptr
, sa
);
367 ptr
= nt_s390_prefix(ptr
, sa
);
372 * Initialize prpsinfo note (new kernel)
374 static void *nt_prpsinfo(void *ptr
)
376 struct elf_prpsinfo prpsinfo
;
378 memset(&prpsinfo
, 0, sizeof(prpsinfo
));
379 prpsinfo
.pr_sname
= 'R';
380 strcpy(prpsinfo
.pr_fname
, "vmlinux");
381 return nt_init(ptr
, NT_PRPSINFO
, &prpsinfo
, sizeof(prpsinfo
),
382 KEXEC_CORE_NOTE_NAME
);
386 * Get vmcoreinfo using lowcore->vmcore_info (new kernel)
388 static void *get_vmcoreinfo_old(unsigned long *size
)
390 char nt_name
[11], *vmcoreinfo
;
394 if (copy_from_oldmem(&addr
, &S390_lowcore
.vmcore_info
, sizeof(addr
)))
396 memset(nt_name
, 0, sizeof(nt_name
));
397 if (copy_from_oldmem(¬e
, addr
, sizeof(note
)))
399 if (copy_from_oldmem(nt_name
, addr
+ sizeof(note
), sizeof(nt_name
) - 1))
401 if (strcmp(nt_name
, "VMCOREINFO") != 0)
403 vmcoreinfo
= kzalloc_panic(note
.n_descsz
);
404 if (copy_from_oldmem(vmcoreinfo
, addr
+ 24, note
.n_descsz
))
406 *size
= note
.n_descsz
;
411 * Initialize vmcoreinfo note (new kernel)
413 static void *nt_vmcoreinfo(void *ptr
)
418 vmcoreinfo
= os_info_old_entry(OS_INFO_VMCOREINFO
, &size
);
420 vmcoreinfo
= get_vmcoreinfo_old(&size
);
423 return nt_init(ptr
, 0, vmcoreinfo
, size
, "VMCOREINFO");
427 * Initialize ELF header (new kernel)
429 static void *ehdr_init(Elf64_Ehdr
*ehdr
, int mem_chunk_cnt
)
431 memset(ehdr
, 0, sizeof(*ehdr
));
432 memcpy(ehdr
->e_ident
, ELFMAG
, SELFMAG
);
433 ehdr
->e_ident
[EI_CLASS
] = ELFCLASS64
;
434 ehdr
->e_ident
[EI_DATA
] = ELFDATA2MSB
;
435 ehdr
->e_ident
[EI_VERSION
] = EV_CURRENT
;
436 memset(ehdr
->e_ident
+ EI_PAD
, 0, EI_NIDENT
- EI_PAD
);
437 ehdr
->e_type
= ET_CORE
;
438 ehdr
->e_machine
= EM_S390
;
439 ehdr
->e_version
= EV_CURRENT
;
440 ehdr
->e_phoff
= sizeof(Elf64_Ehdr
);
441 ehdr
->e_ehsize
= sizeof(Elf64_Ehdr
);
442 ehdr
->e_phentsize
= sizeof(Elf64_Phdr
);
443 ehdr
->e_phnum
= mem_chunk_cnt
+ 1;
448 * Return CPU count for ELF header (new kernel)
450 static int get_cpu_cnt(void)
454 for (i
= 0; zfcpdump_save_areas
[i
]; i
++) {
455 if (zfcpdump_save_areas
[i
]->pref_reg
== 0)
463 * Return memory chunk count for ELF header (new kernel)
465 static int get_mem_chunk_cnt(void)
467 struct mem_chunk
*chunk_array
, *mem_chunk
;
470 chunk_array
= get_memory_layout();
471 for (i
= 0; i
< MEMORY_CHUNKS
; i
++) {
472 mem_chunk
= &chunk_array
[i
];
473 if (chunk_array
[i
].type
!= CHUNK_READ_WRITE
&&
474 chunk_array
[i
].type
!= CHUNK_READ_ONLY
)
476 if (mem_chunk
->size
== 0)
485 * Initialize ELF loads (new kernel)
487 static int loads_init(Elf64_Phdr
*phdr
, u64 loads_offset
)
489 struct mem_chunk
*chunk_array
, *mem_chunk
;
492 chunk_array
= get_memory_layout();
493 for (i
= 0; i
< MEMORY_CHUNKS
; i
++) {
494 mem_chunk
= &chunk_array
[i
];
495 if (mem_chunk
->size
== 0)
497 if (chunk_array
[i
].type
!= CHUNK_READ_WRITE
&&
498 chunk_array
[i
].type
!= CHUNK_READ_ONLY
)
501 phdr
->p_filesz
= mem_chunk
->size
;
502 phdr
->p_type
= PT_LOAD
;
503 phdr
->p_offset
= mem_chunk
->addr
;
504 phdr
->p_vaddr
= mem_chunk
->addr
;
505 phdr
->p_paddr
= mem_chunk
->addr
;
506 phdr
->p_memsz
= mem_chunk
->size
;
507 phdr
->p_flags
= PF_R
| PF_W
| PF_X
;
508 phdr
->p_align
= PAGE_SIZE
;
516 * Initialize notes (new kernel)
518 static void *notes_init(Elf64_Phdr
*phdr
, void *ptr
, u64 notes_offset
)
520 struct save_area
*sa
;
521 void *ptr_start
= ptr
;
524 ptr
= nt_prpsinfo(ptr
);
526 for (i
= 0; zfcpdump_save_areas
[i
]; i
++) {
527 sa
= zfcpdump_save_areas
[i
];
528 if (sa
->pref_reg
== 0)
530 ptr
= fill_cpu_elf_notes(ptr
, sa
);
532 ptr
= nt_vmcoreinfo(ptr
);
533 memset(phdr
, 0, sizeof(*phdr
));
534 phdr
->p_type
= PT_NOTE
;
535 phdr
->p_offset
= notes_offset
;
536 phdr
->p_filesz
= (unsigned long) PTR_SUB(ptr
, ptr_start
);
537 phdr
->p_memsz
= phdr
->p_filesz
;
542 * Create ELF core header (new kernel)
544 int elfcorehdr_alloc(unsigned long long *addr
, unsigned long long *size
)
546 Elf64_Phdr
*phdr_notes
, *phdr_loads
;
552 /* If we are not in kdump or zfcpdump mode return */
553 if (!OLDMEM_BASE
&& ipl_info
.type
!= IPL_TYPE_FCP_DUMP
)
555 /* If elfcorehdr= has been passed via cmdline, we use that one */
556 if (elfcorehdr_addr
!= ELFCORE_ADDR_MAX
)
558 mem_chunk_cnt
= get_mem_chunk_cnt();
560 alloc_size
= 0x1000 + get_cpu_cnt() * 0x300 +
561 mem_chunk_cnt
* sizeof(Elf64_Phdr
);
562 hdr
= kzalloc_panic(alloc_size
);
563 /* Init elf header */
564 ptr
= ehdr_init(hdr
, mem_chunk_cnt
);
565 /* Init program headers */
567 ptr
= PTR_ADD(ptr
, sizeof(Elf64_Phdr
));
569 ptr
= PTR_ADD(ptr
, sizeof(Elf64_Phdr
) * mem_chunk_cnt
);
571 hdr_off
= PTR_DIFF(ptr
, hdr
);
572 ptr
= notes_init(phdr_notes
, ptr
, ((unsigned long) hdr
) + hdr_off
);
574 hdr_off
= PTR_DIFF(ptr
, hdr
);
575 loads_init(phdr_loads
, hdr_off
);
576 *addr
= (unsigned long long) hdr
;
577 elfcorehdr_newmem
= hdr
;
578 *size
= (unsigned long long) hdr_off
;
579 BUG_ON(elfcorehdr_size
> alloc_size
);
584 * Free ELF core header (new kernel)
586 void elfcorehdr_free(unsigned long long addr
)
588 if (!elfcorehdr_newmem
)
590 kfree((void *)(unsigned long)addr
);
594 * Read from ELF header
596 ssize_t
elfcorehdr_read(char *buf
, size_t count
, u64
*ppos
)
598 void *src
= (void *)(unsigned long)*ppos
;
600 src
= elfcorehdr_newmem
? src
: src
- OLDMEM_BASE
;
601 memcpy(buf
, src
, count
);
607 * Read from ELF notes data
609 ssize_t
elfcorehdr_read_notes(char *buf
, size_t count
, u64
*ppos
)
611 void *src
= (void *)(unsigned long)*ppos
;
614 if (elfcorehdr_newmem
) {
615 memcpy(buf
, src
, count
);
617 rc
= copy_from_oldmem(buf
, src
, count
);