aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--arch/s390/include/asm/elf.h2
-rw-r--r--arch/s390/include/asm/ipl.h4
-rw-r--r--arch/s390/include/asm/lowcore.h11
-rw-r--r--arch/s390/include/asm/sigp.h6
-rw-r--r--arch/s390/include/asm/switch_to.h13
-rw-r--r--arch/s390/kernel/crash_dump.c58
-rw-r--r--arch/s390/kernel/machine_kexec.c8
-rw-r--r--arch/s390/kernel/smp.c31
-rw-r--r--drivers/s390/char/zcore.c18
9 files changed, 123 insertions, 28 deletions
diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h
index 27735ae06a78..f6e43d39e3d8 100644
--- a/arch/s390/include/asm/elf.h
+++ b/arch/s390/include/asm/elf.h
@@ -226,6 +226,6 @@ int arch_setup_additional_pages(struct linux_binprm *, int);
226extern unsigned long arch_randomize_brk(struct mm_struct *mm); 226extern unsigned long arch_randomize_brk(struct mm_struct *mm);
227#define arch_randomize_brk arch_randomize_brk 227#define arch_randomize_brk arch_randomize_brk
228 228
229void *fill_cpu_elf_notes(void *ptr, struct save_area *sa); 229void *fill_cpu_elf_notes(void *ptr, struct save_area *sa, __vector128 *vxrs);
230 230
231#endif 231#endif
diff --git a/arch/s390/include/asm/ipl.h b/arch/s390/include/asm/ipl.h
index c81661e756a0..ece606c2ee86 100644
--- a/arch/s390/include/asm/ipl.h
+++ b/arch/s390/include/asm/ipl.h
@@ -89,12 +89,12 @@ extern u32 ipl_flags;
89extern u32 dump_prefix_page; 89extern u32 dump_prefix_page;
90 90
91struct dump_save_areas { 91struct dump_save_areas {
92 struct save_area **areas; 92 struct save_area_ext **areas;
93 int count; 93 int count;
94}; 94};
95 95
96extern struct dump_save_areas dump_save_areas; 96extern struct dump_save_areas dump_save_areas;
97struct save_area *dump_save_area_create(int cpu); 97struct save_area_ext *dump_save_area_create(int cpu);
98 98
99extern void do_reipl(void); 99extern void do_reipl(void);
100extern void do_halt(void); 100extern void do_halt(void);
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h
index d812cf1a8177..6cc51fe84410 100644
--- a/arch/s390/include/asm/lowcore.h
+++ b/arch/s390/include/asm/lowcore.h
@@ -11,6 +11,7 @@
11#include <linux/types.h> 11#include <linux/types.h>
12#include <asm/ptrace.h> 12#include <asm/ptrace.h>
13#include <asm/cpu.h> 13#include <asm/cpu.h>
14#include <asm/types.h>
14 15
15#ifdef CONFIG_32BIT 16#ifdef CONFIG_32BIT
16 17
@@ -31,6 +32,11 @@ struct save_area {
31 u32 ctrl_regs[16]; 32 u32 ctrl_regs[16];
32} __packed; 33} __packed;
33 34
35struct save_area_ext {
36 struct save_area sa;
37 __vector128 vx_regs[32];
38};
39
34struct _lowcore { 40struct _lowcore {
35 psw_t restart_psw; /* 0x0000 */ 41 psw_t restart_psw; /* 0x0000 */
36 psw_t restart_old_psw; /* 0x0008 */ 42 psw_t restart_old_psw; /* 0x0008 */
@@ -183,6 +189,11 @@ struct save_area {
183 u64 ctrl_regs[16]; 189 u64 ctrl_regs[16];
184} __packed; 190} __packed;
185 191
192struct save_area_ext {
193 struct save_area sa;
194 __vector128 vx_regs[32];
195};
196
186struct _lowcore { 197struct _lowcore {
187 __u8 pad_0x0000[0x0014-0x0000]; /* 0x0000 */ 198 __u8 pad_0x0000[0x0014-0x0000]; /* 0x0000 */
188 __u32 ipl_parmblock_ptr; /* 0x0014 */ 199 __u32 ipl_parmblock_ptr; /* 0x0014 */
diff --git a/arch/s390/include/asm/sigp.h b/arch/s390/include/asm/sigp.h
index bf9c823d4020..49576115dbb7 100644
--- a/arch/s390/include/asm/sigp.h
+++ b/arch/s390/include/asm/sigp.h
@@ -15,6 +15,7 @@
15#define SIGP_SET_ARCHITECTURE 18 15#define SIGP_SET_ARCHITECTURE 18
16#define SIGP_COND_EMERGENCY_SIGNAL 19 16#define SIGP_COND_EMERGENCY_SIGNAL 19
17#define SIGP_SENSE_RUNNING 21 17#define SIGP_SENSE_RUNNING 21
18#define SIGP_STORE_ADDITIONAL_STATUS 23
18 19
19/* SIGP condition codes */ 20/* SIGP condition codes */
20#define SIGP_CC_ORDER_CODE_ACCEPTED 0 21#define SIGP_CC_ORDER_CODE_ACCEPTED 0
@@ -33,9 +34,10 @@
33 34
34#ifndef __ASSEMBLY__ 35#ifndef __ASSEMBLY__
35 36
36static inline int __pcpu_sigp(u16 addr, u8 order, u32 parm, u32 *status) 37static inline int __pcpu_sigp(u16 addr, u8 order, unsigned long parm,
38 u32 *status)
37{ 39{
38 register unsigned int reg1 asm ("1") = parm; 40 register unsigned long reg1 asm ("1") = parm;
39 int cc; 41 int cc;
40 42
41 asm volatile( 43 asm volatile(
diff --git a/arch/s390/include/asm/switch_to.h b/arch/s390/include/asm/switch_to.h
index 0e0109578021..2542a7e4c8b4 100644
--- a/arch/s390/include/asm/switch_to.h
+++ b/arch/s390/include/asm/switch_to.h
@@ -114,6 +114,19 @@ static inline void save_vx_regs(__vector128 *vxrs)
114 : "=Q" (*(addrtype *) vxrs) : : "1"); 114 : "=Q" (*(addrtype *) vxrs) : : "1");
115} 115}
116 116
117static inline void save_vx_regs_safe(__vector128 *vxrs)
118{
119 unsigned long cr0, flags;
120
121 flags = arch_local_irq_save();
122 __ctl_store(cr0, 0, 0);
123 __ctl_set_bit(0, 17);
124 __ctl_set_bit(0, 18);
125 save_vx_regs(vxrs);
126 __ctl_load(cr0, 0, 0);
127 arch_local_irq_restore(flags);
128}
129
117static inline void restore_vx_regs(__vector128 *vxrs) 130static inline void restore_vx_regs(__vector128 *vxrs)
118{ 131{
119 typedef struct { __vector128 _[__NUM_VXRS]; } addrtype; 132 typedef struct { __vector128 _[__NUM_VXRS]; } addrtype;
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 */
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c
index 719e27b2cf22..4685337fa7c6 100644
--- a/arch/s390/kernel/machine_kexec.c
+++ b/arch/s390/kernel/machine_kexec.c
@@ -25,6 +25,7 @@
25#include <asm/elf.h> 25#include <asm/elf.h>
26#include <asm/asm-offsets.h> 26#include <asm/asm-offsets.h>
27#include <asm/os_info.h> 27#include <asm/os_info.h>
28#include <asm/switch_to.h>
28 29
29typedef void (*relocate_kernel_t)(kimage_entry_t *, unsigned long); 30typedef void (*relocate_kernel_t)(kimage_entry_t *, unsigned long);
30 31
@@ -43,7 +44,7 @@ static void add_elf_notes(int cpu)
43 44
44 memcpy((void *) (4608UL + sa->pref_reg), sa, sizeof(*sa)); 45 memcpy((void *) (4608UL + sa->pref_reg), sa, sizeof(*sa));
45 ptr = (u64 *) per_cpu_ptr(crash_notes, cpu); 46 ptr = (u64 *) per_cpu_ptr(crash_notes, cpu);
46 ptr = fill_cpu_elf_notes(ptr, sa); 47 ptr = fill_cpu_elf_notes(ptr, sa, NULL);
47 memset(ptr, 0, sizeof(struct elf_note)); 48 memset(ptr, 0, sizeof(struct elf_note));
48} 49}
49 50
@@ -53,8 +54,11 @@ static void add_elf_notes(int cpu)
53static void setup_regs(void) 54static void setup_regs(void)
54{ 55{
55 unsigned long sa = S390_lowcore.prefixreg_save_area + SAVE_AREA_BASE; 56 unsigned long sa = S390_lowcore.prefixreg_save_area + SAVE_AREA_BASE;
57 struct _lowcore *lc;
56 int cpu, this_cpu; 58 int cpu, this_cpu;
57 59
60 /* Get lowcore pointer from store status of this CPU (absolute zero) */
61 lc = (struct _lowcore *)(unsigned long)S390_lowcore.prefixreg_save_area;
58 this_cpu = smp_find_processor_id(stap()); 62 this_cpu = smp_find_processor_id(stap());
59 add_elf_notes(this_cpu); 63 add_elf_notes(this_cpu);
60 for_each_online_cpu(cpu) { 64 for_each_online_cpu(cpu) {
@@ -64,6 +68,8 @@ static void setup_regs(void)
64 continue; 68 continue;
65 add_elf_notes(cpu); 69 add_elf_notes(cpu);
66 } 70 }
71 if (MACHINE_HAS_VX)
72 save_vx_regs_safe((void *) lc->vector_save_area_addr);
67 /* Copy dump CPU store status info to absolute zero */ 73 /* Copy dump CPU store status info to absolute zero */
68 memcpy((void *) SAVE_AREA_BASE, (void *) sa, sizeof(struct save_area)); 74 memcpy((void *) SAVE_AREA_BASE, (void *) sa, sizeof(struct save_area));
69} 75}
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 13cae5b152d7..6fd9e60101f1 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -83,7 +83,8 @@ DEFINE_MUTEX(smp_cpu_state_mutex);
83/* 83/*
84 * Signal processor helper functions. 84 * Signal processor helper functions.
85 */ 85 */
86static inline int __pcpu_sigp_relax(u16 addr, u8 order, u32 parm, u32 *status) 86static inline int __pcpu_sigp_relax(u16 addr, u8 order, unsigned long parm,
87 u32 *status)
87{ 88{
88 int cc; 89 int cc;
89 90
@@ -515,35 +516,53 @@ EXPORT_SYMBOL(smp_ctl_clear_bit);
515static void __init smp_get_save_area(int cpu, u16 address) 516static void __init smp_get_save_area(int cpu, u16 address)
516{ 517{
517 void *lc = pcpu_devices[0].lowcore; 518 void *lc = pcpu_devices[0].lowcore;
518 struct save_area *save_area; 519 struct save_area_ext *sa_ext;
520 unsigned long vx_sa;
519 521
520 if (is_kdump_kernel()) 522 if (is_kdump_kernel())
521 return; 523 return;
522 if (!OLDMEM_BASE && (address == boot_cpu_address || 524 if (!OLDMEM_BASE && (address == boot_cpu_address ||
523 ipl_info.type != IPL_TYPE_FCP_DUMP)) 525 ipl_info.type != IPL_TYPE_FCP_DUMP))
524 return; 526 return;
525 save_area = dump_save_area_create(cpu); 527 sa_ext = dump_save_area_create(cpu);
526 if (!save_area) 528 if (!sa_ext)
527 panic("could not allocate memory for save area\n"); 529 panic("could not allocate memory for save area\n");
528 if (address == boot_cpu_address) { 530 if (address == boot_cpu_address) {
529 /* Copy the registers of the boot cpu. */ 531 /* Copy the registers of the boot cpu. */
530 copy_oldmem_page(1, (void *) save_area, sizeof(*save_area), 532 copy_oldmem_page(1, (void *) &sa_ext->sa, sizeof(sa_ext->sa),
531 SAVE_AREA_BASE - PAGE_SIZE, 0); 533 SAVE_AREA_BASE - PAGE_SIZE, 0);
534 if (MACHINE_HAS_VX)
535 save_vx_regs_safe(sa_ext->vx_regs);
532 return; 536 return;
533 } 537 }
534 /* Get the registers of a non-boot cpu. */ 538 /* Get the registers of a non-boot cpu. */
535 __pcpu_sigp_relax(address, SIGP_STOP_AND_STORE_STATUS, 0, NULL); 539 __pcpu_sigp_relax(address, SIGP_STOP_AND_STORE_STATUS, 0, NULL);
536 memcpy_real(save_area, lc + SAVE_AREA_BASE, sizeof(*save_area)); 540 memcpy_real(&sa_ext->sa, lc + SAVE_AREA_BASE, sizeof(sa_ext->sa));
541 if (!MACHINE_HAS_VX)
542 return;
543 /* Get the VX registers */
544 vx_sa = __get_free_page(GFP_KERNEL);
545 if (!vx_sa)
546 panic("could not allocate memory for VX save area\n");
547 __pcpu_sigp_relax(address, SIGP_STORE_ADDITIONAL_STATUS, vx_sa, NULL);
548 memcpy(sa_ext->vx_regs, (void *) vx_sa, sizeof(sa_ext->vx_regs));
549 free_page(vx_sa);
537} 550}
538 551
539int smp_store_status(int cpu) 552int smp_store_status(int cpu)
540{ 553{
554 unsigned long vx_sa;
541 struct pcpu *pcpu; 555 struct pcpu *pcpu;
542 556
543 pcpu = pcpu_devices + cpu; 557 pcpu = pcpu_devices + cpu;
544 if (__pcpu_sigp_relax(pcpu->address, SIGP_STOP_AND_STORE_STATUS, 558 if (__pcpu_sigp_relax(pcpu->address, SIGP_STOP_AND_STORE_STATUS,
545 0, NULL) != SIGP_CC_ORDER_CODE_ACCEPTED) 559 0, NULL) != SIGP_CC_ORDER_CODE_ACCEPTED)
546 return -EIO; 560 return -EIO;
561 if (!MACHINE_HAS_VX)
562 return 0;
563 vx_sa = __pa(pcpu->lowcore->vector_save_area_addr);
564 __pcpu_sigp_relax(pcpu->address, SIGP_STORE_ADDITIONAL_STATUS,
565 vx_sa, NULL);
547 return 0; 566 return 0;
548} 567}
549 568
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 1884653e4472..efcf48481c5f 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -28,6 +28,7 @@
28#include <asm/processor.h> 28#include <asm/processor.h>
29#include <asm/irqflags.h> 29#include <asm/irqflags.h>
30#include <asm/checksum.h> 30#include <asm/checksum.h>
31#include <asm/switch_to.h>
31#include "sclp.h" 32#include "sclp.h"
32 33
33#define TRACE(x...) debug_sprintf_event(zcore_dbf, 1, x) 34#define TRACE(x...) debug_sprintf_event(zcore_dbf, 1, x)
@@ -149,18 +150,21 @@ static int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count)
149 150
150static int __init init_cpu_info(enum arch_id arch) 151static int __init init_cpu_info(enum arch_id arch)
151{ 152{
152 struct save_area *sa; 153 struct save_area_ext *sa_ext;
153 154
154 /* get info for boot cpu from lowcore, stored in the HSA */ 155 /* get info for boot cpu from lowcore, stored in the HSA */
155 156
156 sa = dump_save_area_create(0); 157 sa_ext = dump_save_area_create(0);
157 if (!sa) 158 if (!sa_ext)
158 return -ENOMEM; 159 return -ENOMEM;
159 if (memcpy_hsa_kernel(sa, sys_info.sa_base, sys_info.sa_size) < 0) { 160 if (memcpy_hsa_kernel(&sa_ext->sa, sys_info.sa_base,
161 sys_info.sa_size) < 0) {
160 TRACE("could not copy from HSA\n"); 162 TRACE("could not copy from HSA\n");
161 kfree(sa); 163 kfree(sa_ext);
162 return -EIO; 164 return -EIO;
163 } 165 }
166 if (MACHINE_HAS_VX)
167 save_vx_regs_safe(sa_ext->vx_regs);
164 return 0; 168 return 0;
165} 169}
166 170
@@ -258,7 +262,7 @@ static int zcore_add_lc(char __user *buf, unsigned long start, size_t count)
258 unsigned long sa_start, sa_end; /* save area range */ 262 unsigned long sa_start, sa_end; /* save area range */
259 unsigned long prefix; 263 unsigned long prefix;
260 unsigned long sa_off, len, buf_off; 264 unsigned long sa_off, len, buf_off;
261 struct save_area *save_area = dump_save_areas.areas[i]; 265 struct save_area *save_area = &dump_save_areas.areas[i]->sa;
262 266
263 prefix = save_area->pref_reg; 267 prefix = save_area->pref_reg;
264 sa_start = prefix + sys_info.sa_base; 268 sa_start = prefix + sys_info.sa_base;
@@ -612,7 +616,7 @@ static void __init zcore_header_init(int arch, struct zcore_header *hdr,
612 hdr->tod = get_tod_clock(); 616 hdr->tod = get_tod_clock();
613 get_cpu_id(&hdr->cpu_id); 617 get_cpu_id(&hdr->cpu_id);
614 for (i = 0; i < dump_save_areas.count; i++) { 618 for (i = 0; i < dump_save_areas.count; i++) {
615 prefix = dump_save_areas.areas[i]->pref_reg; 619 prefix = dump_save_areas.areas[i]->sa.pref_reg;
616 hdr->real_cpu_cnt++; 620 hdr->real_cpu_cnt++;
617 if (!prefix) 621 if (!prefix)
618 continue; 622 continue;