aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/char/zcore.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/char/zcore.c')
-rw-r--r--drivers/s390/char/zcore.c163
1 files changed, 67 insertions, 96 deletions
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 82daa3c1dc9c..3438658b66b7 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -15,6 +15,7 @@
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/miscdevice.h> 16#include <linux/miscdevice.h>
17#include <linux/debugfs.h> 17#include <linux/debugfs.h>
18#include <asm/asm-offsets.h>
18#include <asm/ipl.h> 19#include <asm/ipl.h>
19#include <asm/sclp.h> 20#include <asm/sclp.h>
20#include <asm/setup.h> 21#include <asm/setup.h>
@@ -40,12 +41,12 @@ enum arch_id {
40/* dump system info */ 41/* dump system info */
41 42
42struct sys_info { 43struct sys_info {
43 enum arch_id arch; 44 enum arch_id arch;
44 unsigned long sa_base; 45 unsigned long sa_base;
45 u32 sa_size; 46 u32 sa_size;
46 int cpu_map[NR_CPUS]; 47 int cpu_map[NR_CPUS];
47 unsigned long mem_size; 48 unsigned long mem_size;
48 union save_area lc_mask; 49 struct save_area lc_mask;
49}; 50};
50 51
51struct ipib_info { 52struct ipib_info {
@@ -183,52 +184,9 @@ static int memcpy_real_user(void __user *dest, unsigned long src, size_t count)
183 return 0; 184 return 0;
184} 185}
185 186
186#ifdef __s390x__
187/*
188 * Convert s390x (64 bit) cpu info to s390 (32 bit) cpu info
189 */
190static void __init s390x_to_s390_regs(union save_area *out, union save_area *in,
191 int cpu)
192{
193 int i;
194
195 for (i = 0; i < 16; i++) {
196 out->s390.gp_regs[i] = in->s390x.gp_regs[i] & 0x00000000ffffffff;
197 out->s390.acc_regs[i] = in->s390x.acc_regs[i];
198 out->s390.ctrl_regs[i] =
199 in->s390x.ctrl_regs[i] & 0x00000000ffffffff;
200 }
201 /* locore for 31 bit has only space for fpregs 0,2,4,6 */
202 out->s390.fp_regs[0] = in->s390x.fp_regs[0];
203 out->s390.fp_regs[1] = in->s390x.fp_regs[2];
204 out->s390.fp_regs[2] = in->s390x.fp_regs[4];
205 out->s390.fp_regs[3] = in->s390x.fp_regs[6];
206 memcpy(&(out->s390.psw[0]), &(in->s390x.psw[0]), 4);
207 out->s390.psw[1] |= 0x8; /* set bit 12 */
208 memcpy(&(out->s390.psw[4]),&(in->s390x.psw[12]), 4);
209 out->s390.psw[4] |= 0x80; /* set (31bit) addressing bit */
210 out->s390.pref_reg = in->s390x.pref_reg;
211 out->s390.timer = in->s390x.timer;
212 out->s390.clk_cmp = in->s390x.clk_cmp;
213}
214
215static void __init s390x_to_s390_save_areas(void)
216{
217 int i = 1;
218 static union save_area tmp;
219
220 while (zfcpdump_save_areas[i]) {
221 s390x_to_s390_regs(&tmp, zfcpdump_save_areas[i], i);
222 memcpy(zfcpdump_save_areas[i], &tmp, sizeof(tmp));
223 i++;
224 }
225}
226
227#endif /* __s390x__ */
228
229static int __init init_cpu_info(enum arch_id arch) 187static int __init init_cpu_info(enum arch_id arch)
230{ 188{
231 union save_area *sa; 189 struct save_area *sa;
232 190
233 /* get info for boot cpu from lowcore, stored in the HSA */ 191 /* get info for boot cpu from lowcore, stored in the HSA */
234 192
@@ -241,20 +199,12 @@ static int __init init_cpu_info(enum arch_id arch)
241 return -EIO; 199 return -EIO;
242 } 200 }
243 zfcpdump_save_areas[0] = sa; 201 zfcpdump_save_areas[0] = sa;
244
245#ifdef __s390x__
246 /* convert s390x regs to s390, if we are dumping an s390 Linux */
247
248 if (arch == ARCH_S390)
249 s390x_to_s390_save_areas();
250#endif
251
252 return 0; 202 return 0;
253} 203}
254 204
255static DEFINE_MUTEX(zcore_mutex); 205static DEFINE_MUTEX(zcore_mutex);
256 206
257#define DUMP_VERSION 0x3 207#define DUMP_VERSION 0x5
258#define DUMP_MAGIC 0xa8190173618f23fdULL 208#define DUMP_MAGIC 0xa8190173618f23fdULL
259#define DUMP_ARCH_S390X 2 209#define DUMP_ARCH_S390X 2
260#define DUMP_ARCH_S390 1 210#define DUMP_ARCH_S390 1
@@ -279,7 +229,14 @@ struct zcore_header {
279 u32 volnr; 229 u32 volnr;
280 u32 build_arch; 230 u32 build_arch;
281 u64 rmem_size; 231 u64 rmem_size;
282 char pad2[4016]; 232 u8 mvdump;
233 u16 cpu_cnt;
234 u16 real_cpu_cnt;
235 u8 end_pad1[0x200-0x061];
236 u64 mvdump_sign;
237 u64 mvdump_zipl_time;
238 u8 end_pad2[0x800-0x210];
239 u32 lc_vec[512];
283} __attribute__((packed,__aligned__(16))); 240} __attribute__((packed,__aligned__(16)));
284 241
285static struct zcore_header zcore_header = { 242static struct zcore_header zcore_header = {
@@ -289,7 +246,7 @@ static struct zcore_header zcore_header = {
289 .dump_level = 0, 246 .dump_level = 0,
290 .page_size = PAGE_SIZE, 247 .page_size = PAGE_SIZE,
291 .mem_start = 0, 248 .mem_start = 0,
292#ifdef __s390x__ 249#ifdef CONFIG_64BIT
293 .build_arch = DUMP_ARCH_S390X, 250 .build_arch = DUMP_ARCH_S390X,
294#else 251#else
295 .build_arch = DUMP_ARCH_S390, 252 .build_arch = DUMP_ARCH_S390,
@@ -340,11 +297,7 @@ static int zcore_add_lc(char __user *buf, unsigned long start, size_t count)
340 unsigned long prefix; 297 unsigned long prefix;
341 unsigned long sa_off, len, buf_off; 298 unsigned long sa_off, len, buf_off;
342 299
343 if (sys_info.arch == ARCH_S390) 300 prefix = zfcpdump_save_areas[i]->pref_reg;
344 prefix = zfcpdump_save_areas[i]->s390.pref_reg;
345 else
346 prefix = zfcpdump_save_areas[i]->s390x.pref_reg;
347
348 sa_start = prefix + sys_info.sa_base; 301 sa_start = prefix + sys_info.sa_base;
349 sa_end = prefix + sys_info.sa_base + sys_info.sa_size; 302 sa_end = prefix + sys_info.sa_base + sys_info.sa_size;
350 303
@@ -561,34 +514,39 @@ static const struct file_operations zcore_reipl_fops = {
561 .release = zcore_reipl_release, 514 .release = zcore_reipl_release,
562}; 515};
563 516
517#ifdef CONFIG_32BIT
564 518
565static void __init set_s390_lc_mask(union save_area *map) 519static void __init set_lc_mask(struct save_area *map)
566{ 520{
567 memset(&map->s390.ext_save, 0xff, sizeof(map->s390.ext_save)); 521 memset(&map->ext_save, 0xff, sizeof(map->ext_save));
568 memset(&map->s390.timer, 0xff, sizeof(map->s390.timer)); 522 memset(&map->timer, 0xff, sizeof(map->timer));
569 memset(&map->s390.clk_cmp, 0xff, sizeof(map->s390.clk_cmp)); 523 memset(&map->clk_cmp, 0xff, sizeof(map->clk_cmp));
570 memset(&map->s390.psw, 0xff, sizeof(map->s390.psw)); 524 memset(&map->psw, 0xff, sizeof(map->psw));
571 memset(&map->s390.pref_reg, 0xff, sizeof(map->s390.pref_reg)); 525 memset(&map->pref_reg, 0xff, sizeof(map->pref_reg));
572 memset(&map->s390.acc_regs, 0xff, sizeof(map->s390.acc_regs)); 526 memset(&map->acc_regs, 0xff, sizeof(map->acc_regs));
573 memset(&map->s390.fp_regs, 0xff, sizeof(map->s390.fp_regs)); 527 memset(&map->fp_regs, 0xff, sizeof(map->fp_regs));
574 memset(&map->s390.gp_regs, 0xff, sizeof(map->s390.gp_regs)); 528 memset(&map->gp_regs, 0xff, sizeof(map->gp_regs));
575 memset(&map->s390.ctrl_regs, 0xff, sizeof(map->s390.ctrl_regs)); 529 memset(&map->ctrl_regs, 0xff, sizeof(map->ctrl_regs));
576} 530}
577 531
578static void __init set_s390x_lc_mask(union save_area *map) 532#else /* CONFIG_32BIT */
533
534static void __init set_lc_mask(struct save_area *map)
579{ 535{
580 memset(&map->s390x.fp_regs, 0xff, sizeof(map->s390x.fp_regs)); 536 memset(&map->fp_regs, 0xff, sizeof(map->fp_regs));
581 memset(&map->s390x.gp_regs, 0xff, sizeof(map->s390x.gp_regs)); 537 memset(&map->gp_regs, 0xff, sizeof(map->gp_regs));
582 memset(&map->s390x.psw, 0xff, sizeof(map->s390x.psw)); 538 memset(&map->psw, 0xff, sizeof(map->psw));
583 memset(&map->s390x.pref_reg, 0xff, sizeof(map->s390x.pref_reg)); 539 memset(&map->pref_reg, 0xff, sizeof(map->pref_reg));
584 memset(&map->s390x.fp_ctrl_reg, 0xff, sizeof(map->s390x.fp_ctrl_reg)); 540 memset(&map->fp_ctrl_reg, 0xff, sizeof(map->fp_ctrl_reg));
585 memset(&map->s390x.tod_reg, 0xff, sizeof(map->s390x.tod_reg)); 541 memset(&map->tod_reg, 0xff, sizeof(map->tod_reg));
586 memset(&map->s390x.timer, 0xff, sizeof(map->s390x.timer)); 542 memset(&map->timer, 0xff, sizeof(map->timer));
587 memset(&map->s390x.clk_cmp, 0xff, sizeof(map->s390x.clk_cmp)); 543 memset(&map->clk_cmp, 0xff, sizeof(map->clk_cmp));
588 memset(&map->s390x.acc_regs, 0xff, sizeof(map->s390x.acc_regs)); 544 memset(&map->acc_regs, 0xff, sizeof(map->acc_regs));
589 memset(&map->s390x.ctrl_regs, 0xff, sizeof(map->s390x.ctrl_regs)); 545 memset(&map->ctrl_regs, 0xff, sizeof(map->ctrl_regs));
590} 546}
591 547
548#endif /* CONFIG_32BIT */
549
592/* 550/*
593 * Initialize dump globals for a given architecture 551 * Initialize dump globals for a given architecture
594 */ 552 */
@@ -599,21 +557,18 @@ static int __init sys_info_init(enum arch_id arch)
599 switch (arch) { 557 switch (arch) {
600 case ARCH_S390X: 558 case ARCH_S390X:
601 pr_alert("DETECTED 'S390X (64 bit) OS'\n"); 559 pr_alert("DETECTED 'S390X (64 bit) OS'\n");
602 sys_info.sa_base = SAVE_AREA_BASE_S390X;
603 sys_info.sa_size = sizeof(struct save_area_s390x);
604 set_s390x_lc_mask(&sys_info.lc_mask);
605 break; 560 break;
606 case ARCH_S390: 561 case ARCH_S390:
607 pr_alert("DETECTED 'S390 (32 bit) OS'\n"); 562 pr_alert("DETECTED 'S390 (32 bit) OS'\n");
608 sys_info.sa_base = SAVE_AREA_BASE_S390;
609 sys_info.sa_size = sizeof(struct save_area_s390);
610 set_s390_lc_mask(&sys_info.lc_mask);
611 break; 563 break;
612 default: 564 default:
613 pr_alert("0x%x is an unknown architecture.\n",arch); 565 pr_alert("0x%x is an unknown architecture.\n",arch);
614 return -EINVAL; 566 return -EINVAL;
615 } 567 }
568 sys_info.sa_base = SAVE_AREA_BASE;
569 sys_info.sa_size = sizeof(struct save_area);
616 sys_info.arch = arch; 570 sys_info.arch = arch;
571 set_lc_mask(&sys_info.lc_mask);
617 rc = init_cpu_info(arch); 572 rc = init_cpu_info(arch);
618 if (rc) 573 if (rc)
619 return rc; 574 return rc;
@@ -660,8 +615,9 @@ static int __init get_mem_size(unsigned long *mem)
660 615
661static int __init zcore_header_init(int arch, struct zcore_header *hdr) 616static int __init zcore_header_init(int arch, struct zcore_header *hdr)
662{ 617{
663 int rc; 618 int rc, i;
664 unsigned long memory = 0; 619 unsigned long memory = 0;
620 u32 prefix;
665 621
666 if (arch == ARCH_S390X) 622 if (arch == ARCH_S390X)
667 hdr->arch_id = DUMP_ARCH_S390X; 623 hdr->arch_id = DUMP_ARCH_S390X;
@@ -676,6 +632,14 @@ static int __init zcore_header_init(int arch, struct zcore_header *hdr)
676 hdr->num_pages = memory / PAGE_SIZE; 632 hdr->num_pages = memory / PAGE_SIZE;
677 hdr->tod = get_clock(); 633 hdr->tod = get_clock();
678 get_cpu_id(&hdr->cpu_id); 634 get_cpu_id(&hdr->cpu_id);
635 for (i = 0; zfcpdump_save_areas[i]; i++) {
636 prefix = zfcpdump_save_areas[i]->pref_reg;
637 hdr->real_cpu_cnt++;
638 if (!prefix)
639 continue;
640 hdr->lc_vec[hdr->cpu_cnt] = prefix;
641 hdr->cpu_cnt++;
642 }
679 return 0; 643 return 0;
680} 644}
681 645
@@ -741,14 +705,21 @@ static int __init zcore_init(void)
741 if (rc) 705 if (rc)
742 goto fail; 706 goto fail;
743 707
744#ifndef __s390x__ 708#ifdef CONFIG_64BIT
709 if (arch == ARCH_S390) {
710 pr_alert("The 64-bit dump tool cannot be used for a "
711 "32-bit system\n");
712 rc = -EINVAL;
713 goto fail;
714 }
715#else /* CONFIG_64BIT */
745 if (arch == ARCH_S390X) { 716 if (arch == ARCH_S390X) {
746 pr_alert("The 32-bit dump tool cannot be used for a " 717 pr_alert("The 32-bit dump tool cannot be used for a "
747 "64-bit system\n"); 718 "64-bit system\n");
748 rc = -EINVAL; 719 rc = -EINVAL;
749 goto fail; 720 goto fail;
750 } 721 }
751#endif 722#endif /* CONFIG_64BIT */
752 723
753 rc = sys_info_init(arch); 724 rc = sys_info_init(arch);
754 if (rc) 725 if (rc)