diff options
-rw-r--r-- | arch/s390/include/asm/ipl.h | 9 | ||||
-rw-r--r-- | arch/s390/include/asm/smp.h | 1 | ||||
-rw-r--r-- | arch/s390/kernel/crash_dump.c | 34 | ||||
-rw-r--r-- | arch/s390/kernel/smp.c | 11 | ||||
-rw-r--r-- | drivers/s390/char/zcore.c | 20 |
5 files changed, 49 insertions, 26 deletions
diff --git a/arch/s390/include/asm/ipl.h b/arch/s390/include/asm/ipl.h index 2bd6cb897b90..ea7d9d6ab06e 100644 --- a/arch/s390/include/asm/ipl.h +++ b/arch/s390/include/asm/ipl.h | |||
@@ -7,6 +7,7 @@ | |||
7 | #ifndef _ASM_S390_IPL_H | 7 | #ifndef _ASM_S390_IPL_H |
8 | #define _ASM_S390_IPL_H | 8 | #define _ASM_S390_IPL_H |
9 | 9 | ||
10 | #include <asm/lowcore.h> | ||
10 | #include <asm/types.h> | 11 | #include <asm/types.h> |
11 | #include <asm/cio.h> | 12 | #include <asm/cio.h> |
12 | #include <asm/setup.h> | 13 | #include <asm/setup.h> |
@@ -88,6 +89,14 @@ extern u32 ipl_flags; | |||
88 | extern u32 dump_prefix_page; | 89 | extern u32 dump_prefix_page; |
89 | extern unsigned int zfcpdump_prefix_array[]; | 90 | extern unsigned int zfcpdump_prefix_array[]; |
90 | 91 | ||
92 | struct dump_save_areas { | ||
93 | struct save_area **areas; | ||
94 | int count; | ||
95 | }; | ||
96 | |||
97 | extern struct dump_save_areas dump_save_areas; | ||
98 | struct save_area *dump_save_area_create(int cpu); | ||
99 | |||
91 | extern void do_reipl(void); | 100 | extern void do_reipl(void); |
92 | extern void do_halt(void); | 101 | extern void do_halt(void); |
93 | extern void do_poff(void); | 102 | extern void do_poff(void); |
diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h index b64f15c3b4cc..ac9bed8e103f 100644 --- a/arch/s390/include/asm/smp.h +++ b/arch/s390/include/asm/smp.h | |||
@@ -14,7 +14,6 @@ | |||
14 | #define raw_smp_processor_id() (S390_lowcore.cpu_nr) | 14 | #define raw_smp_processor_id() (S390_lowcore.cpu_nr) |
15 | 15 | ||
16 | extern struct mutex smp_cpu_state_mutex; | 16 | extern struct mutex smp_cpu_state_mutex; |
17 | extern struct save_area *zfcpdump_save_areas[NR_CPUS + 1]; | ||
18 | 17 | ||
19 | extern int __cpu_up(unsigned int cpu, struct task_struct *tidle); | 18 | extern int __cpu_up(unsigned int cpu, struct task_struct *tidle); |
20 | 19 | ||
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c index 3db6af0601a5..f45b2ab0cb81 100644 --- a/arch/s390/kernel/crash_dump.c +++ b/arch/s390/kernel/crash_dump.c | |||
@@ -22,6 +22,32 @@ | |||
22 | #define PTR_SUB(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)))) | 23 | #define PTR_DIFF(x, y) ((unsigned long)(((char *) (x)) - ((unsigned long) (y)))) |
24 | 24 | ||
25 | struct dump_save_areas dump_save_areas; | ||
26 | |||
27 | /* | ||
28 | * Allocate and add a save area for a CPU | ||
29 | */ | ||
30 | struct save_area *dump_save_area_create(int cpu) | ||
31 | { | ||
32 | struct save_area **save_areas, *save_area; | ||
33 | |||
34 | save_area = kmalloc(sizeof(*save_area), GFP_KERNEL); | ||
35 | if (!save_area) | ||
36 | return NULL; | ||
37 | if (cpu + 1 > dump_save_areas.count) { | ||
38 | dump_save_areas.count = cpu + 1; | ||
39 | save_areas = krealloc(dump_save_areas.areas, | ||
40 | dump_save_areas.count * sizeof(void *), | ||
41 | GFP_KERNEL | __GFP_ZERO); | ||
42 | if (!save_areas) { | ||
43 | kfree(save_area); | ||
44 | return NULL; | ||
45 | } | ||
46 | dump_save_areas.areas = save_areas; | ||
47 | } | ||
48 | dump_save_areas.areas[cpu] = save_area; | ||
49 | return save_area; | ||
50 | } | ||
25 | 51 | ||
26 | /* | 52 | /* |
27 | * Return physical address for virtual address | 53 | * Return physical address for virtual address |
@@ -450,8 +476,8 @@ static int get_cpu_cnt(void) | |||
450 | { | 476 | { |
451 | int i, cpus = 0; | 477 | int i, cpus = 0; |
452 | 478 | ||
453 | for (i = 0; zfcpdump_save_areas[i]; i++) { | 479 | for (i = 0; i < dump_save_areas.count; i++) { |
454 | if (zfcpdump_save_areas[i]->pref_reg == 0) | 480 | if (dump_save_areas.areas[i]->pref_reg == 0) |
455 | continue; | 481 | continue; |
456 | cpus++; | 482 | cpus++; |
457 | } | 483 | } |
@@ -522,8 +548,8 @@ static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset) | |||
522 | 548 | ||
523 | ptr = nt_prpsinfo(ptr); | 549 | ptr = nt_prpsinfo(ptr); |
524 | 550 | ||
525 | for (i = 0; zfcpdump_save_areas[i]; i++) { | 551 | for (i = 0; i < dump_save_areas.count; i++) { |
526 | sa = zfcpdump_save_areas[i]; | 552 | sa = dump_save_areas.areas[i]; |
527 | if (sa->pref_reg == 0) | 553 | if (sa->pref_reg == 0) |
528 | continue; | 554 | continue; |
529 | ptr = fill_cpu_elf_notes(ptr, sa); | 555 | ptr = fill_cpu_elf_notes(ptr, sa); |
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index cca6cf6abacc..739313db71e5 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -533,9 +533,6 @@ EXPORT_SYMBOL(smp_ctl_clear_bit); | |||
533 | 533 | ||
534 | #if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_CRASH_DUMP) | 534 | #if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_CRASH_DUMP) |
535 | 535 | ||
536 | struct save_area *zfcpdump_save_areas[NR_CPUS + 1]; | ||
537 | EXPORT_SYMBOL_GPL(zfcpdump_save_areas); | ||
538 | |||
539 | static void __init smp_get_save_area(int cpu, u16 address) | 536 | static void __init smp_get_save_area(int cpu, u16 address) |
540 | { | 537 | { |
541 | void *lc = pcpu_devices[0].lowcore; | 538 | void *lc = pcpu_devices[0].lowcore; |
@@ -546,15 +543,9 @@ static void __init smp_get_save_area(int cpu, u16 address) | |||
546 | if (!OLDMEM_BASE && (address == boot_cpu_address || | 543 | if (!OLDMEM_BASE && (address == boot_cpu_address || |
547 | ipl_info.type != IPL_TYPE_FCP_DUMP)) | 544 | ipl_info.type != IPL_TYPE_FCP_DUMP)) |
548 | return; | 545 | return; |
549 | if (cpu >= NR_CPUS) { | 546 | save_area = dump_save_area_create(cpu); |
550 | pr_warning("CPU %i exceeds the maximum %i and is excluded " | ||
551 | "from the dump\n", cpu, NR_CPUS - 1); | ||
552 | return; | ||
553 | } | ||
554 | save_area = kmalloc(sizeof(struct save_area), GFP_KERNEL); | ||
555 | if (!save_area) | 547 | if (!save_area) |
556 | panic("could not allocate memory for save area\n"); | 548 | panic("could not allocate memory for save area\n"); |
557 | zfcpdump_save_areas[cpu] = save_area; | ||
558 | #ifdef CONFIG_CRASH_DUMP | 549 | #ifdef CONFIG_CRASH_DUMP |
559 | if (address == boot_cpu_address) { | 550 | if (address == boot_cpu_address) { |
560 | /* Copy the registers of the boot cpu. */ | 551 | /* Copy the registers of the boot cpu. */ |
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index 794820a123d0..ffb1fcf0bf5b 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c | |||
@@ -151,7 +151,7 @@ static int __init init_cpu_info(enum arch_id arch) | |||
151 | 151 | ||
152 | /* get info for boot cpu from lowcore, stored in the HSA */ | 152 | /* get info for boot cpu from lowcore, stored in the HSA */ |
153 | 153 | ||
154 | sa = kmalloc(sizeof(*sa), GFP_KERNEL); | 154 | sa = dump_save_area_create(0); |
155 | if (!sa) | 155 | if (!sa) |
156 | return -ENOMEM; | 156 | return -ENOMEM; |
157 | if (memcpy_hsa_kernel(sa, sys_info.sa_base, sys_info.sa_size) < 0) { | 157 | if (memcpy_hsa_kernel(sa, sys_info.sa_base, sys_info.sa_size) < 0) { |
@@ -159,7 +159,6 @@ static int __init init_cpu_info(enum arch_id arch) | |||
159 | kfree(sa); | 159 | kfree(sa); |
160 | return -EIO; | 160 | return -EIO; |
161 | } | 161 | } |
162 | zfcpdump_save_areas[0] = sa; | ||
163 | return 0; | 162 | return 0; |
164 | } | 163 | } |
165 | 164 | ||
@@ -246,24 +245,25 @@ static int copy_lc(void __user *buf, void *sa, int sa_off, int len) | |||
246 | static int zcore_add_lc(char __user *buf, unsigned long start, size_t count) | 245 | static int zcore_add_lc(char __user *buf, unsigned long start, size_t count) |
247 | { | 246 | { |
248 | unsigned long end; | 247 | unsigned long end; |
249 | int i = 0; | 248 | int i; |
250 | 249 | ||
251 | if (count == 0) | 250 | if (count == 0) |
252 | return 0; | 251 | return 0; |
253 | 252 | ||
254 | end = start + count; | 253 | end = start + count; |
255 | while (zfcpdump_save_areas[i]) { | 254 | for (i = 0; i < dump_save_areas.count; i++) { |
256 | unsigned long cp_start, cp_end; /* copy range */ | 255 | unsigned long cp_start, cp_end; /* copy range */ |
257 | unsigned long sa_start, sa_end; /* save area range */ | 256 | unsigned long sa_start, sa_end; /* save area range */ |
258 | unsigned long prefix; | 257 | unsigned long prefix; |
259 | unsigned long sa_off, len, buf_off; | 258 | unsigned long sa_off, len, buf_off; |
259 | struct save_area *save_area = dump_save_areas.areas[i]; | ||
260 | 260 | ||
261 | prefix = zfcpdump_save_areas[i]->pref_reg; | 261 | prefix = save_area->pref_reg; |
262 | sa_start = prefix + sys_info.sa_base; | 262 | sa_start = prefix + sys_info.sa_base; |
263 | sa_end = prefix + sys_info.sa_base + sys_info.sa_size; | 263 | sa_end = prefix + sys_info.sa_base + sys_info.sa_size; |
264 | 264 | ||
265 | if ((end < sa_start) || (start > sa_end)) | 265 | if ((end < sa_start) || (start > sa_end)) |
266 | goto next; | 266 | continue; |
267 | cp_start = max(start, sa_start); | 267 | cp_start = max(start, sa_start); |
268 | cp_end = min(end, sa_end); | 268 | cp_end = min(end, sa_end); |
269 | 269 | ||
@@ -272,10 +272,8 @@ static int zcore_add_lc(char __user *buf, unsigned long start, size_t count) | |||
272 | len = cp_end - cp_start; | 272 | len = cp_end - cp_start; |
273 | 273 | ||
274 | TRACE("copy_lc for: %lx\n", start); | 274 | TRACE("copy_lc for: %lx\n", start); |
275 | if (copy_lc(buf + buf_off, zfcpdump_save_areas[i], sa_off, len)) | 275 | if (copy_lc(buf + buf_off, save_area, sa_off, len)) |
276 | return -EFAULT; | 276 | return -EFAULT; |
277 | next: | ||
278 | i++; | ||
279 | } | 277 | } |
280 | return 0; | 278 | return 0; |
281 | } | 279 | } |
@@ -637,8 +635,8 @@ static void __init zcore_header_init(int arch, struct zcore_header *hdr, | |||
637 | hdr->num_pages = mem_size / PAGE_SIZE; | 635 | hdr->num_pages = mem_size / PAGE_SIZE; |
638 | hdr->tod = get_tod_clock(); | 636 | hdr->tod = get_tod_clock(); |
639 | get_cpu_id(&hdr->cpu_id); | 637 | get_cpu_id(&hdr->cpu_id); |
640 | for (i = 0; zfcpdump_save_areas[i]; i++) { | 638 | for (i = 0; i < dump_save_areas.count; i++) { |
641 | prefix = zfcpdump_save_areas[i]->pref_reg; | 639 | prefix = dump_save_areas.areas[i]->pref_reg; |
642 | hdr->real_cpu_cnt++; | 640 | hdr->real_cpu_cnt++; |
643 | if (!prefix) | 641 | if (!prefix) |
644 | continue; | 642 | continue; |