aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/crash_dump.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/crash_dump.c')
-rw-r--r--arch/s390/kernel/crash_dump.c75
1 files changed, 49 insertions, 26 deletions
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c
index c84f33d51f7b..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
@@ -40,28 +66,25 @@ static inline void *load_real_addr(void *addr)
40} 66}
41 67
42/* 68/*
43 * Copy up to one page to vmalloc or real memory 69 * Copy real to virtual or real memory
44 */ 70 */
45static ssize_t copy_page_real(void *buf, void *src, size_t csize) 71static int copy_from_realmem(void *dest, void *src, size_t count)
46{ 72{
47 size_t size; 73 unsigned long size;
48 74
49 if (is_vmalloc_addr(buf)) { 75 if (!count)
50 BUG_ON(csize >= PAGE_SIZE); 76 return 0;
51 /* If buf is not page aligned, copy first part */ 77 if (!is_vmalloc_or_module_addr(dest))
52 size = min(roundup(__pa(buf), PAGE_SIZE) - __pa(buf), csize); 78 return memcpy_real(dest, src, count);
53 if (size) { 79 do {
54 if (memcpy_real(load_real_addr(buf), src, size)) 80 size = min(count, PAGE_SIZE - (__pa(dest) & ~PAGE_MASK));
55 return -EFAULT; 81 if (memcpy_real(load_real_addr(dest), src, size))
56 buf += size; 82 return -EFAULT;
57 src += size; 83 count -= size;
58 } 84 dest += size;
59 /* Copy second part */ 85 src += size;
60 size = csize - size; 86 } while (count);
61 return (size) ? memcpy_real(load_real_addr(buf), src, size) : 0; 87 return 0;
62 } else {
63 return memcpy_real(buf, src, csize);
64 }
65} 88}
66 89
67/* 90/*
@@ -114,7 +137,7 @@ static ssize_t copy_oldmem_page_kdump(char *buf, size_t csize,
114 rc = copy_to_user_real((void __force __user *) buf, 137 rc = copy_to_user_real((void __force __user *) buf,
115 (void *) src, csize); 138 (void *) src, csize);
116 else 139 else
117 rc = copy_page_real(buf, (void *) src, csize); 140 rc = copy_from_realmem(buf, (void *) src, csize);
118 return (rc == 0) ? rc : csize; 141 return (rc == 0) ? rc : csize;
119} 142}
120 143
@@ -210,7 +233,7 @@ int copy_from_oldmem(void *dest, void *src, size_t count)
210 if (OLDMEM_BASE) { 233 if (OLDMEM_BASE) {
211 if ((unsigned long) src < OLDMEM_SIZE) { 234 if ((unsigned long) src < OLDMEM_SIZE) {
212 copied = min(count, OLDMEM_SIZE - (unsigned long) src); 235 copied = min(count, OLDMEM_SIZE - (unsigned long) src);
213 rc = memcpy_real(dest, src + OLDMEM_BASE, copied); 236 rc = copy_from_realmem(dest, src + OLDMEM_BASE, copied);
214 if (rc) 237 if (rc)
215 return rc; 238 return rc;
216 } 239 }
@@ -223,7 +246,7 @@ int copy_from_oldmem(void *dest, void *src, size_t count)
223 return rc; 246 return rc;
224 } 247 }
225 } 248 }
226 return memcpy_real(dest + copied, src + copied, count - copied); 249 return copy_from_realmem(dest + copied, src + copied, count - copied);
227} 250}
228 251
229/* 252/*
@@ -453,8 +476,8 @@ static int get_cpu_cnt(void)
453{ 476{
454 int i, cpus = 0; 477 int i, cpus = 0;
455 478
456 for (i = 0; zfcpdump_save_areas[i]; i++) { 479 for (i = 0; i < dump_save_areas.count; i++) {
457 if (zfcpdump_save_areas[i]->pref_reg == 0) 480 if (dump_save_areas.areas[i]->pref_reg == 0)
458 continue; 481 continue;
459 cpus++; 482 cpus++;
460 } 483 }
@@ -525,8 +548,8 @@ static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)
525 548
526 ptr = nt_prpsinfo(ptr); 549 ptr = nt_prpsinfo(ptr);
527 550
528 for (i = 0; zfcpdump_save_areas[i]; i++) { 551 for (i = 0; i < dump_save_areas.count; i++) {
529 sa = zfcpdump_save_areas[i]; 552 sa = dump_save_areas.areas[i];
530 if (sa->pref_reg == 0) 553 if (sa->pref_reg == 0)
531 continue; 554 continue;
532 ptr = fill_cpu_elf_notes(ptr, sa); 555 ptr = fill_cpu_elf_notes(ptr, sa);