aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/char/zcore.c101
1 files changed, 94 insertions, 7 deletions
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 047dd92ae804..7fd84be11931 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -29,6 +29,7 @@
29 29
30#define TO_USER 0 30#define TO_USER 0
31#define TO_KERNEL 1 31#define TO_KERNEL 1
32#define CHUNK_INFO_SIZE 34 /* 2 16-byte char, each followed by blank */
32 33
33enum arch_id { 34enum arch_id {
34 ARCH_S390 = 0, 35 ARCH_S390 = 0,
@@ -51,6 +52,7 @@ static struct debug_info *zcore_dbf;
51static int hsa_available; 52static int hsa_available;
52static struct dentry *zcore_dir; 53static struct dentry *zcore_dir;
53static struct dentry *zcore_file; 54static struct dentry *zcore_file;
55static struct dentry *zcore_memmap_file;
54 56
55/* 57/*
56 * Copy memory from HSA to kernel or user memory (not reentrant): 58 * Copy memory from HSA to kernel or user memory (not reentrant):
@@ -476,6 +478,54 @@ static const struct file_operations zcore_fops = {
476 .release = zcore_release, 478 .release = zcore_release,
477}; 479};
478 480
481static ssize_t zcore_memmap_read(struct file *filp, char __user *buf,
482 size_t count, loff_t *ppos)
483{
484 return simple_read_from_buffer(buf, count, ppos, filp->private_data,
485 MEMORY_CHUNKS * CHUNK_INFO_SIZE);
486}
487
488static int zcore_memmap_open(struct inode *inode, struct file *filp)
489{
490 int i;
491 char *buf;
492 struct mem_chunk *chunk_array;
493
494 chunk_array = kzalloc(MEMORY_CHUNKS * sizeof(struct mem_chunk),
495 GFP_KERNEL);
496 if (!chunk_array)
497 return -ENOMEM;
498 detect_memory_layout(chunk_array);
499 buf = kzalloc(MEMORY_CHUNKS * CHUNK_INFO_SIZE, GFP_KERNEL);
500 if (!buf) {
501 kfree(chunk_array);
502 return -ENOMEM;
503 }
504 for (i = 0; i < MEMORY_CHUNKS; i++) {
505 sprintf(buf + (i * CHUNK_INFO_SIZE), "%016llx %016llx ",
506 (unsigned long long) chunk_array[i].addr,
507 (unsigned long long) chunk_array[i].size);
508 if (chunk_array[i].size == 0)
509 break;
510 }
511 kfree(chunk_array);
512 filp->private_data = buf;
513 return 0;
514}
515
516static int zcore_memmap_release(struct inode *inode, struct file *filp)
517{
518 kfree(filp->private_data);
519 return 0;
520}
521
522static const struct file_operations zcore_memmap_fops = {
523 .owner = THIS_MODULE,
524 .read = zcore_memmap_read,
525 .open = zcore_memmap_open,
526 .release = zcore_memmap_release,
527};
528
479 529
480static void __init set_s390_lc_mask(union save_area *map) 530static void __init set_s390_lc_mask(union save_area *map)
481{ 531{
@@ -554,18 +604,44 @@ static int __init check_sdias(void)
554 return 0; 604 return 0;
555} 605}
556 606
557static void __init zcore_header_init(int arch, struct zcore_header *hdr) 607static int __init get_mem_size(unsigned long *mem)
608{
609 int i;
610 struct mem_chunk *chunk_array;
611
612 chunk_array = kzalloc(MEMORY_CHUNKS * sizeof(struct mem_chunk),
613 GFP_KERNEL);
614 if (!chunk_array)
615 return -ENOMEM;
616 detect_memory_layout(chunk_array);
617 for (i = 0; i < MEMORY_CHUNKS; i++) {
618 if (chunk_array[i].size == 0)
619 break;
620 *mem += chunk_array[i].size;
621 }
622 kfree(chunk_array);
623 return 0;
624}
625
626static int __init zcore_header_init(int arch, struct zcore_header *hdr)
558{ 627{
628 int rc;
629 unsigned long memory = 0;
630
559 if (arch == ARCH_S390X) 631 if (arch == ARCH_S390X)
560 hdr->arch_id = DUMP_ARCH_S390X; 632 hdr->arch_id = DUMP_ARCH_S390X;
561 else 633 else
562 hdr->arch_id = DUMP_ARCH_S390; 634 hdr->arch_id = DUMP_ARCH_S390;
563 hdr->mem_size = sys_info.mem_size; 635 rc = get_mem_size(&memory);
564 hdr->rmem_size = sys_info.mem_size; 636 if (rc)
637 return rc;
638 hdr->mem_size = memory;
639 hdr->rmem_size = memory;
565 hdr->mem_end = sys_info.mem_size; 640 hdr->mem_end = sys_info.mem_size;
566 hdr->num_pages = sys_info.mem_size / PAGE_SIZE; 641 hdr->num_pages = memory / PAGE_SIZE;
567 hdr->tod = get_clock(); 642 hdr->tod = get_clock();
568 get_cpu_id(&hdr->cpu_id); 643 get_cpu_id(&hdr->cpu_id);
644 return 0;
569} 645}
570 646
571static int __init zcore_init(void) 647static int __init zcore_init(void)
@@ -608,7 +684,9 @@ static int __init zcore_init(void)
608 if (rc) 684 if (rc)
609 goto fail; 685 goto fail;
610 686
611 zcore_header_init(arch, &zcore_header); 687 rc = zcore_header_init(arch, &zcore_header);
688 if (rc)
689 goto fail;
612 690
613 zcore_dir = debugfs_create_dir("zcore" , NULL); 691 zcore_dir = debugfs_create_dir("zcore" , NULL);
614 if (!zcore_dir) { 692 if (!zcore_dir) {
@@ -618,13 +696,22 @@ static int __init zcore_init(void)
618 zcore_file = debugfs_create_file("mem", S_IRUSR, zcore_dir, NULL, 696 zcore_file = debugfs_create_file("mem", S_IRUSR, zcore_dir, NULL,
619 &zcore_fops); 697 &zcore_fops);
620 if (!zcore_file) { 698 if (!zcore_file) {
621 debugfs_remove(zcore_dir);
622 rc = -ENOMEM; 699 rc = -ENOMEM;
623 goto fail; 700 goto fail_dir;
701 }
702 zcore_memmap_file = debugfs_create_file("memmap", S_IRUSR, zcore_dir,
703 NULL, &zcore_memmap_fops);
704 if (!zcore_memmap_file) {
705 rc = -ENOMEM;
706 goto fail_file;
624 } 707 }
625 hsa_available = 1; 708 hsa_available = 1;
626 return 0; 709 return 0;
627 710
711fail_file:
712 debugfs_remove(zcore_file);
713fail_dir:
714 debugfs_remove(zcore_dir);
628fail: 715fail:
629 diag308(DIAG308_REL_HSA, NULL); 716 diag308(DIAG308_REL_HSA, NULL);
630 return rc; 717 return rc;