aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/include/asm/ipl.h9
-rw-r--r--arch/s390/include/asm/smp.h1
-rw-r--r--arch/s390/kernel/crash_dump.c34
-rw-r--r--arch/s390/kernel/smp.c11
-rw-r--r--drivers/s390/char/zcore.c20
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;
88extern u32 dump_prefix_page; 89extern u32 dump_prefix_page;
89extern unsigned int zfcpdump_prefix_array[]; 90extern unsigned int zfcpdump_prefix_array[];
90 91
92struct dump_save_areas {
93 struct save_area **areas;
94 int count;
95};
96
97extern struct dump_save_areas dump_save_areas;
98struct save_area *dump_save_area_create(int cpu);
99
91extern void do_reipl(void); 100extern void do_reipl(void);
92extern void do_halt(void); 101extern void do_halt(void);
93extern void do_poff(void); 102extern 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
16extern struct mutex smp_cpu_state_mutex; 16extern struct mutex smp_cpu_state_mutex;
17extern struct save_area *zfcpdump_save_areas[NR_CPUS + 1];
18 17
19extern int __cpu_up(unsigned int cpu, struct task_struct *tidle); 18extern 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
25struct dump_save_areas dump_save_areas;
26
27/*
28 * Allocate and add a save area for a CPU
29 */
30struct 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
536struct save_area *zfcpdump_save_areas[NR_CPUS + 1];
537EXPORT_SYMBOL_GPL(zfcpdump_save_areas);
538
539static void __init smp_get_save_area(int cpu, u16 address) 536static 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)
246static int zcore_add_lc(char __user *buf, unsigned long start, size_t count) 245static 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;
277next:
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;