diff options
Diffstat (limited to 'arch/s390/kernel/crash_dump.c')
-rw-r--r-- | arch/s390/kernel/crash_dump.c | 42 |
1 files changed, 20 insertions, 22 deletions
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c index c84f33d51f7b..7dd21720e5b0 100644 --- a/arch/s390/kernel/crash_dump.c +++ b/arch/s390/kernel/crash_dump.c | |||
@@ -40,28 +40,26 @@ static inline void *load_real_addr(void *addr) | |||
40 | } | 40 | } |
41 | 41 | ||
42 | /* | 42 | /* |
43 | * Copy up to one page to vmalloc or real memory | 43 | * Copy real to virtual or real memory |
44 | */ | 44 | */ |
45 | static ssize_t copy_page_real(void *buf, void *src, size_t csize) | 45 | static int copy_from_realmem(void *dest, void *src, size_t count) |
46 | { | 46 | { |
47 | size_t size; | 47 | unsigned long size; |
48 | int rc; | ||
48 | 49 | ||
49 | if (is_vmalloc_addr(buf)) { | 50 | if (!count) |
50 | BUG_ON(csize >= PAGE_SIZE); | 51 | return 0; |
51 | /* If buf is not page aligned, copy first part */ | 52 | if (!is_vmalloc_or_module_addr(dest)) |
52 | size = min(roundup(__pa(buf), PAGE_SIZE) - __pa(buf), csize); | 53 | return memcpy_real(dest, src, count); |
53 | if (size) { | 54 | do { |
54 | if (memcpy_real(load_real_addr(buf), src, size)) | 55 | size = min(count, PAGE_SIZE - (__pa(dest) & ~PAGE_MASK)); |
55 | return -EFAULT; | 56 | if (memcpy_real(load_real_addr(dest), src, size)) |
56 | buf += size; | 57 | return -EFAULT; |
57 | src += size; | 58 | count -= size; |
58 | } | 59 | dest += size; |
59 | /* Copy second part */ | 60 | src += size; |
60 | size = csize - size; | 61 | } while (count); |
61 | return (size) ? memcpy_real(load_real_addr(buf), src, size) : 0; | 62 | return 0; |
62 | } else { | ||
63 | return memcpy_real(buf, src, csize); | ||
64 | } | ||
65 | } | 63 | } |
66 | 64 | ||
67 | /* | 65 | /* |
@@ -114,7 +112,7 @@ static ssize_t copy_oldmem_page_kdump(char *buf, size_t csize, | |||
114 | rc = copy_to_user_real((void __force __user *) buf, | 112 | rc = copy_to_user_real((void __force __user *) buf, |
115 | (void *) src, csize); | 113 | (void *) src, csize); |
116 | else | 114 | else |
117 | rc = copy_page_real(buf, (void *) src, csize); | 115 | rc = copy_from_realmem(buf, (void *) src, csize); |
118 | return (rc == 0) ? rc : csize; | 116 | return (rc == 0) ? rc : csize; |
119 | } | 117 | } |
120 | 118 | ||
@@ -210,7 +208,7 @@ int copy_from_oldmem(void *dest, void *src, size_t count) | |||
210 | if (OLDMEM_BASE) { | 208 | if (OLDMEM_BASE) { |
211 | if ((unsigned long) src < OLDMEM_SIZE) { | 209 | if ((unsigned long) src < OLDMEM_SIZE) { |
212 | copied = min(count, OLDMEM_SIZE - (unsigned long) src); | 210 | copied = min(count, OLDMEM_SIZE - (unsigned long) src); |
213 | rc = memcpy_real(dest, src + OLDMEM_BASE, copied); | 211 | rc = copy_from_realmem(dest, src + OLDMEM_BASE, copied); |
214 | if (rc) | 212 | if (rc) |
215 | return rc; | 213 | return rc; |
216 | } | 214 | } |
@@ -223,7 +221,7 @@ int copy_from_oldmem(void *dest, void *src, size_t count) | |||
223 | return rc; | 221 | return rc; |
224 | } | 222 | } |
225 | } | 223 | } |
226 | return memcpy_real(dest + copied, src + copied, count - copied); | 224 | return copy_from_realmem(dest + copied, src + copied, count - copied); |
227 | } | 225 | } |
228 | 226 | ||
229 | /* | 227 | /* |