aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Holzheu <holzheu@linux.vnet.ibm.com>2013-09-11 17:24:54 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-11 18:59:15 -0400
commit6f79d33228fa7cf900826738a39f287cae96cd91 (patch)
tree219851a19eb86c91c77241cb00b3889719fdab23
parent11e376a3f9ffa85bf444b65df5326612b083c501 (diff)
s390/vmcore: use vmcore for zfcpdump
Modify the s390 copy_oldmem_page() and remap_oldmem_pfn_range() function for zfcpdump to read from the HSA memory if memory below HSA_SIZE bytes is requested. Otherwise real memory is used. Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com> Cc: HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com> Cc: Jan Willeke <willeke@de.ibm.com> Cc: Vivek Goyal <vgoyal@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/s390/Kconfig3
-rw-r--r--arch/s390/include/asm/sclp.h1
-rw-r--r--arch/s390/kernel/crash_dump.c122
-rw-r--r--drivers/s390/char/zcore.c6
4 files changed, 110 insertions, 22 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index fb2723e8ba65..3ec272859e1e 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -526,6 +526,7 @@ config CRASH_DUMP
526 bool "kernel crash dumps" 526 bool "kernel crash dumps"
527 depends on 64BIT && SMP 527 depends on 64BIT && SMP
528 select KEXEC 528 select KEXEC
529 select ZFCPDUMP
529 help 530 help
530 Generate crash dump after being started by kexec. 531 Generate crash dump after being started by kexec.
531 Crash dump kernels are loaded in the main kernel with kexec-tools 532 Crash dump kernels are loaded in the main kernel with kexec-tools
@@ -536,7 +537,7 @@ config CRASH_DUMP
536config ZFCPDUMP 537config ZFCPDUMP
537 def_bool n 538 def_bool n
538 prompt "zfcpdump support" 539 prompt "zfcpdump support"
539 select SMP 540 depends on SMP
540 help 541 help
541 Select this option if you want to build an zfcpdump enabled kernel. 542 Select this option if you want to build an zfcpdump enabled kernel.
542 Refer to <file:Documentation/s390/zfcpdump.txt> for more details on this. 543 Refer to <file:Documentation/s390/zfcpdump.txt> for more details on this.
diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h
index 06a136136047..7dc7f9c63b65 100644
--- a/arch/s390/include/asm/sclp.h
+++ b/arch/s390/include/asm/sclp.h
@@ -56,5 +56,6 @@ bool sclp_has_linemode(void);
56bool sclp_has_vt220(void); 56bool sclp_has_vt220(void);
57int sclp_pci_configure(u32 fid); 57int sclp_pci_configure(u32 fid);
58int sclp_pci_deconfigure(u32 fid); 58int sclp_pci_deconfigure(u32 fid);
59int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode);
59 60
60#endif /* _ASM_S390_SCLP_H */ 61#endif /* _ASM_S390_SCLP_H */
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c
index 3e776158b330..c84f33d51f7b 100644
--- a/arch/s390/kernel/crash_dump.c
+++ b/arch/s390/kernel/crash_dump.c
@@ -16,6 +16,7 @@
16#include <asm/os_info.h> 16#include <asm/os_info.h>
17#include <asm/elf.h> 17#include <asm/elf.h>
18#include <asm/ipl.h> 18#include <asm/ipl.h>
19#include <asm/sclp.h>
19 20
20#define PTR_ADD(x, y) (((char *) (x)) + ((unsigned long) (y))) 21#define PTR_ADD(x, y) (((char *) (x)) + ((unsigned long) (y)))
21#define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y))) 22#define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y)))
@@ -69,22 +70,41 @@ static ssize_t copy_page_real(void *buf, void *src, size_t csize)
69static void *elfcorehdr_newmem; 70static void *elfcorehdr_newmem;
70 71
71/* 72/*
72 * Copy one page from "oldmem" 73 * Copy one page from zfcpdump "oldmem"
74 *
75 * For pages below ZFCPDUMP_HSA_SIZE memory from the HSA is copied. Otherwise
76 * real memory copy is used.
77 */
78static ssize_t copy_oldmem_page_zfcpdump(char *buf, size_t csize,
79 unsigned long src, int userbuf)
80{
81 int rc;
82
83 if (src < ZFCPDUMP_HSA_SIZE) {
84 rc = memcpy_hsa(buf, src, csize, userbuf);
85 } else {
86 if (userbuf)
87 rc = copy_to_user_real((void __force __user *) buf,
88 (void *) src, csize);
89 else
90 rc = memcpy_real(buf, (void *) src, csize);
91 }
92 return rc ? rc : csize;
93}
94
95/*
96 * Copy one page from kdump "oldmem"
73 * 97 *
74 * For the kdump reserved memory this functions performs a swap operation: 98 * For the kdump reserved memory this functions performs a swap operation:
75 * - [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE] is mapped to [0 - OLDMEM_SIZE]. 99 * - [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE] is mapped to [0 - OLDMEM_SIZE].
76 * - [0 - OLDMEM_SIZE] is mapped to [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE] 100 * - [0 - OLDMEM_SIZE] is mapped to [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE]
77 */ 101 */
78ssize_t copy_oldmem_page(unsigned long pfn, char *buf, 102static ssize_t copy_oldmem_page_kdump(char *buf, size_t csize,
79 size_t csize, unsigned long offset, int userbuf) 103 unsigned long src, int userbuf)
104
80{ 105{
81 unsigned long src;
82 int rc; 106 int rc;
83 107
84 if (!csize)
85 return 0;
86
87 src = (pfn << PAGE_SHIFT) + offset;
88 if (src < OLDMEM_SIZE) 108 if (src < OLDMEM_SIZE)
89 src += OLDMEM_BASE; 109 src += OLDMEM_BASE;
90 else if (src > OLDMEM_BASE && 110 else if (src > OLDMEM_BASE &&
@@ -95,17 +115,35 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
95 (void *) src, csize); 115 (void *) src, csize);
96 else 116 else
97 rc = copy_page_real(buf, (void *) src, csize); 117 rc = copy_page_real(buf, (void *) src, csize);
98 return (rc == 0) ? csize : rc; 118 return (rc == 0) ? rc : csize;
99} 119}
100 120
101/* 121/*
102 * Remap "oldmem" 122 * Copy one page from "oldmem"
123 */
124ssize_t copy_oldmem_page(unsigned long pfn, char *buf, size_t csize,
125 unsigned long offset, int userbuf)
126{
127 unsigned long src;
128
129 if (!csize)
130 return 0;
131 src = (pfn << PAGE_SHIFT) + offset;
132 if (OLDMEM_BASE)
133 return copy_oldmem_page_kdump(buf, csize, src, userbuf);
134 else
135 return copy_oldmem_page_zfcpdump(buf, csize, src, userbuf);
136}
137
138/*
139 * Remap "oldmem" for kdump
103 * 140 *
104 * For the kdump reserved memory this functions performs a swap operation: 141 * For the kdump reserved memory this functions performs a swap operation:
105 * [0 - OLDMEM_SIZE] is mapped to [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE] 142 * [0 - OLDMEM_SIZE] is mapped to [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE]
106 */ 143 */
107int remap_oldmem_pfn_range(struct vm_area_struct *vma, unsigned long from, 144static int remap_oldmem_pfn_range_kdump(struct vm_area_struct *vma,
108 unsigned long pfn, unsigned long size, pgprot_t prot) 145 unsigned long from, unsigned long pfn,
146 unsigned long size, pgprot_t prot)
109{ 147{
110 unsigned long size_old; 148 unsigned long size_old;
111 int rc; 149 int rc;
@@ -125,6 +163,43 @@ int remap_oldmem_pfn_range(struct vm_area_struct *vma, unsigned long from,
125} 163}
126 164
127/* 165/*
166 * Remap "oldmem" for zfcpdump
167 *
168 * We only map available memory above ZFCPDUMP_HSA_SIZE. Memory below
169 * ZFCPDUMP_HSA_SIZE is read on demand using the copy_oldmem_page() function.
170 */
171static int remap_oldmem_pfn_range_zfcpdump(struct vm_area_struct *vma,
172 unsigned long from,
173 unsigned long pfn,
174 unsigned long size, pgprot_t prot)
175{
176 unsigned long size_hsa;
177
178 if (pfn < ZFCPDUMP_HSA_SIZE >> PAGE_SHIFT) {
179 size_hsa = min(size, ZFCPDUMP_HSA_SIZE - (pfn << PAGE_SHIFT));
180 if (size == size_hsa)
181 return 0;
182 size -= size_hsa;
183 from += size_hsa;
184 pfn += size_hsa >> PAGE_SHIFT;
185 }
186 return remap_pfn_range(vma, from, pfn, size, prot);
187}
188
189/*
190 * Remap "oldmem" for kdump or zfcpdump
191 */
192int remap_oldmem_pfn_range(struct vm_area_struct *vma, unsigned long from,
193 unsigned long pfn, unsigned long size, pgprot_t prot)
194{
195 if (OLDMEM_BASE)
196 return remap_oldmem_pfn_range_kdump(vma, from, pfn, size, prot);
197 else
198 return remap_oldmem_pfn_range_zfcpdump(vma, from, pfn, size,
199 prot);
200}
201
202/*
128 * Copy memory from old kernel 203 * Copy memory from old kernel
129 */ 204 */
130int copy_from_oldmem(void *dest, void *src, size_t count) 205int copy_from_oldmem(void *dest, void *src, size_t count)
@@ -132,11 +207,21 @@ int copy_from_oldmem(void *dest, void *src, size_t count)
132 unsigned long copied = 0; 207 unsigned long copied = 0;
133 int rc; 208 int rc;
134 209
135 if ((unsigned long) src < OLDMEM_SIZE) { 210 if (OLDMEM_BASE) {
136 copied = min(count, OLDMEM_SIZE - (unsigned long) src); 211 if ((unsigned long) src < OLDMEM_SIZE) {
137 rc = memcpy_real(dest, src + OLDMEM_BASE, copied); 212 copied = min(count, OLDMEM_SIZE - (unsigned long) src);
138 if (rc) 213 rc = memcpy_real(dest, src + OLDMEM_BASE, copied);
139 return rc; 214 if (rc)
215 return rc;
216 }
217 } else {
218 if ((unsigned long) src < ZFCPDUMP_HSA_SIZE) {
219 copied = min(count,
220 ZFCPDUMP_HSA_SIZE - (unsigned long) src);
221 rc = memcpy_hsa(dest, (unsigned long) src, copied, 0);
222 if (rc)
223 return rc;
224 }
140 } 225 }
141 return memcpy_real(dest + copied, src + copied, count - copied); 226 return memcpy_real(dest + copied, src + copied, count - copied);
142} 227}
@@ -466,7 +551,8 @@ int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size)
466 u32 alloc_size; 551 u32 alloc_size;
467 u64 hdr_off; 552 u64 hdr_off;
468 553
469 if (!OLDMEM_BASE) 554 /* If we are not in kdump or zfcpdump mode return */
555 if (!OLDMEM_BASE && ipl_info.type != IPL_TYPE_FCP_DUMP)
470 return 0; 556 return 0;
471 /* If elfcorehdr= has been passed via cmdline, we use that one */ 557 /* If elfcorehdr= has been passed via cmdline, we use that one */
472 if (elfcorehdr_addr != ELFCORE_ADDR_MAX) 558 if (elfcorehdr_addr != ELFCORE_ADDR_MAX)
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 9e5e14686e75..794820a123d0 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -30,8 +30,8 @@
30 30
31#define TRACE(x...) debug_sprintf_event(zcore_dbf, 1, x) 31#define TRACE(x...) debug_sprintf_event(zcore_dbf, 1, x)
32 32
33#define TO_USER 0 33#define TO_USER 1
34#define TO_KERNEL 1 34#define TO_KERNEL 0
35#define CHUNK_INFO_SIZE 34 /* 2 16-byte char, each followed by blank */ 35#define CHUNK_INFO_SIZE 34 /* 2 16-byte char, each followed by blank */
36 36
37enum arch_id { 37enum arch_id {
@@ -73,7 +73,7 @@ static struct ipl_parameter_block *ipl_block;
73 * @count: Size of buffer, which should be copied 73 * @count: Size of buffer, which should be copied
74 * @mode: Either TO_KERNEL or TO_USER 74 * @mode: Either TO_KERNEL or TO_USER
75 */ 75 */
76static int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode) 76int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode)
77{ 77{
78 int offs, blk_num; 78 int offs, blk_num;
79 static char buf[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); 79 static char buf[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));