aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/crash_dump.c
diff options
context:
space:
mode:
authorMichael Holzheu <holzheu@linux.vnet.ibm.com>2014-10-06 11:57:43 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2014-10-09 03:14:16 -0400
commita62bc0739253939d6fce40d51d92412252a9bb55 (patch)
tree48247426a662b82c2bd8a4b28054f3b715f60e6d /arch/s390/kernel/crash_dump.c
parent3585cb0280654acbc559a360a839c8d58bb0cb87 (diff)
s390/kdump: add support for vector extension
With this patch for kdump the s390 vector registers are stored into the prepared save areas in the old kernel and into the REGSET_VX_LOW and REGSET_VX_HIGH ELF notes for /proc/vmcore in the new kernel. The NT_S390_VXRS_LOW note contains the lower halves of the first 16 vector registers 0-15. The higher halves are stored in the floating point register ELF note. The NT_S390_VXRS_HIGH contains the full vector registers 16-31. The kernel provides a save area for storing vector register in case of machine checks. A pointer to this save are is stored in the CPU lowcore at offset 0x11b0. This save area is also used to save the registers for kdump. In case of a dumped crashed kdump those areas are used to extract the registers of the production system. The vector registers for remote CPUs are stored using the "store additional status at address" SIGP. For the dump CPU the vector registers are stored with the VSTM instruction. With this patch also zfcpdump stores the vector registers. Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel/crash_dump.c')
-rw-r--r--arch/s390/kernel/crash_dump.c58
1 files changed, 49 insertions, 9 deletions
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c
index a3b9150e6802..9f73c8059022 100644
--- a/arch/s390/kernel/crash_dump.c
+++ b/arch/s390/kernel/crash_dump.c
@@ -46,9 +46,9 @@ struct dump_save_areas dump_save_areas;
46/* 46/*
47 * Allocate and add a save area for a CPU 47 * Allocate and add a save area for a CPU
48 */ 48 */
49struct save_area *dump_save_area_create(int cpu) 49struct save_area_ext *dump_save_area_create(int cpu)
50{ 50{
51 struct save_area **save_areas, *save_area; 51 struct save_area_ext **save_areas, *save_area;
52 52
53 save_area = kmalloc(sizeof(*save_area), GFP_KERNEL); 53 save_area = kmalloc(sizeof(*save_area), GFP_KERNEL);
54 if (!save_area) 54 if (!save_area)
@@ -386,9 +386,45 @@ static void *nt_s390_prefix(void *ptr, struct save_area *sa)
386} 386}
387 387
388/* 388/*
389 * Initialize vxrs high note (full 128 bit VX registers 16-31)
390 */
391static void *nt_s390_vx_high(void *ptr, __vector128 *vx_regs)
392{
393 return nt_init(ptr, NT_S390_VXRS_HIGH, &vx_regs[16],
394 16 * sizeof(__vector128), KEXEC_CORE_NOTE_NAME);
395}
396
397/*
398 * Initialize vxrs low note (lower halves of VX registers 0-15)
399 */
400static void *nt_s390_vx_low(void *ptr, __vector128 *vx_regs)
401{
402 Elf64_Nhdr *note;
403 u64 len;
404 int i;
405
406 note = (Elf64_Nhdr *)ptr;
407 note->n_namesz = strlen(KEXEC_CORE_NOTE_NAME) + 1;
408 note->n_descsz = 16 * 8;
409 note->n_type = NT_S390_VXRS_LOW;
410 len = sizeof(Elf64_Nhdr);
411
412 memcpy(ptr + len, KEXEC_CORE_NOTE_NAME, note->n_namesz);
413 len = roundup(len + note->n_namesz, 4);
414
415 ptr += len;
416 /* Copy lower halves of SIMD registers 0-15 */
417 for (i = 0; i < 16; i++) {
418 memcpy(ptr, &vx_regs[i], 8);
419 ptr += 8;
420 }
421 return ptr;
422}
423
424/*
389 * Fill ELF notes for one CPU with save area registers 425 * Fill ELF notes for one CPU with save area registers
390 */ 426 */
391void *fill_cpu_elf_notes(void *ptr, struct save_area *sa) 427void *fill_cpu_elf_notes(void *ptr, struct save_area *sa, __vector128 *vx_regs)
392{ 428{
393 ptr = nt_prstatus(ptr, sa); 429 ptr = nt_prstatus(ptr, sa);
394 ptr = nt_fpregset(ptr, sa); 430 ptr = nt_fpregset(ptr, sa);
@@ -397,6 +433,10 @@ void *fill_cpu_elf_notes(void *ptr, struct save_area *sa)
397 ptr = nt_s390_tod_preg(ptr, sa); 433 ptr = nt_s390_tod_preg(ptr, sa);
398 ptr = nt_s390_ctrs(ptr, sa); 434 ptr = nt_s390_ctrs(ptr, sa);
399 ptr = nt_s390_prefix(ptr, sa); 435 ptr = nt_s390_prefix(ptr, sa);
436 if (MACHINE_HAS_VX && vx_regs) {
437 ptr = nt_s390_vx_low(ptr, vx_regs);
438 ptr = nt_s390_vx_high(ptr, vx_regs);
439 }
400 return ptr; 440 return ptr;
401} 441}
402 442
@@ -484,7 +524,7 @@ static int get_cpu_cnt(void)
484 int i, cpus = 0; 524 int i, cpus = 0;
485 525
486 for (i = 0; i < dump_save_areas.count; i++) { 526 for (i = 0; i < dump_save_areas.count; i++) {
487 if (dump_save_areas.areas[i]->pref_reg == 0) 527 if (dump_save_areas.areas[i]->sa.pref_reg == 0)
488 continue; 528 continue;
489 cpus++; 529 cpus++;
490 } 530 }
@@ -530,17 +570,17 @@ static void loads_init(Elf64_Phdr *phdr, u64 loads_offset)
530 */ 570 */
531static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset) 571static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)
532{ 572{
533 struct save_area *sa; 573 struct save_area_ext *sa_ext;
534 void *ptr_start = ptr; 574 void *ptr_start = ptr;
535 int i; 575 int i;
536 576
537 ptr = nt_prpsinfo(ptr); 577 ptr = nt_prpsinfo(ptr);
538 578
539 for (i = 0; i < dump_save_areas.count; i++) { 579 for (i = 0; i < dump_save_areas.count; i++) {
540 sa = dump_save_areas.areas[i]; 580 sa_ext = dump_save_areas.areas[i];
541 if (sa->pref_reg == 0) 581 if (sa_ext->sa.pref_reg == 0)
542 continue; 582 continue;
543 ptr = fill_cpu_elf_notes(ptr, sa); 583 ptr = fill_cpu_elf_notes(ptr, &sa_ext->sa, sa_ext->vx_regs);
544 } 584 }
545 ptr = nt_vmcoreinfo(ptr); 585 ptr = nt_vmcoreinfo(ptr);
546 memset(phdr, 0, sizeof(*phdr)); 586 memset(phdr, 0, sizeof(*phdr));
@@ -581,7 +621,7 @@ int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size)
581 621
582 mem_chunk_cnt = get_mem_chunk_cnt(); 622 mem_chunk_cnt = get_mem_chunk_cnt();
583 623
584 alloc_size = 0x1000 + get_cpu_cnt() * 0x300 + 624 alloc_size = 0x1000 + get_cpu_cnt() * 0x4a0 +
585 mem_chunk_cnt * sizeof(Elf64_Phdr); 625 mem_chunk_cnt * sizeof(Elf64_Phdr);
586 hdr = kzalloc_panic(alloc_size); 626 hdr = kzalloc_panic(alloc_size);
587 /* Init elf header */ 627 /* Init elf header */