diff options
Diffstat (limited to 'drivers/s390/char/zcore.c')
-rw-r--r-- | drivers/s390/char/zcore.c | 163 |
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 | ||
42 | struct sys_info { | 43 | struct 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 | ||
51 | struct ipib_info { | 52 | struct 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 | */ | ||
190 | static 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 | |||
215 | static 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 | |||
229 | static int __init init_cpu_info(enum arch_id arch) | 187 | static 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 | ||
255 | static DEFINE_MUTEX(zcore_mutex); | 205 | static 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 | ||
285 | static struct zcore_header zcore_header = { | 242 | static 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 | ||
565 | static void __init set_s390_lc_mask(union save_area *map) | 519 | static 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 | ||
578 | static void __init set_s390x_lc_mask(union save_area *map) | 532 | #else /* CONFIG_32BIT */ |
533 | |||
534 | static 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 | ||
661 | static int __init zcore_header_init(int arch, struct zcore_header *hdr) | 616 | static 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) |