diff options
Diffstat (limited to 'arch/s390/kernel/crash_dump.c')
-rw-r--r-- | arch/s390/kernel/crash_dump.c | 58 |
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 | */ |
49 | struct save_area *dump_save_area_create(int cpu) | 49 | struct 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 | */ | ||
391 | static 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 | */ | ||
400 | static 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 | */ |
391 | void *fill_cpu_elf_notes(void *ptr, struct save_area *sa) | 427 | void *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 | */ |
531 | static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset) | 571 | static 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 */ |