mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
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>
This commit is contained in:
parent
11e376a3f9
commit
6f79d33228
@ -526,6 +526,7 @@ config CRASH_DUMP
|
||||
bool "kernel crash dumps"
|
||||
depends on 64BIT && SMP
|
||||
select KEXEC
|
||||
select ZFCPDUMP
|
||||
help
|
||||
Generate crash dump after being started by kexec.
|
||||
Crash dump kernels are loaded in the main kernel with kexec-tools
|
||||
@ -536,7 +537,7 @@ config CRASH_DUMP
|
||||
config ZFCPDUMP
|
||||
def_bool n
|
||||
prompt "zfcpdump support"
|
||||
select SMP
|
||||
depends on SMP
|
||||
help
|
||||
Select this option if you want to build an zfcpdump enabled kernel.
|
||||
Refer to <file:Documentation/s390/zfcpdump.txt> for more details on this.
|
||||
|
@ -56,5 +56,6 @@ bool sclp_has_linemode(void);
|
||||
bool sclp_has_vt220(void);
|
||||
int sclp_pci_configure(u32 fid);
|
||||
int sclp_pci_deconfigure(u32 fid);
|
||||
int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode);
|
||||
|
||||
#endif /* _ASM_S390_SCLP_H */
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <asm/os_info.h>
|
||||
#include <asm/elf.h>
|
||||
#include <asm/ipl.h>
|
||||
#include <asm/sclp.h>
|
||||
|
||||
#define PTR_ADD(x, y) (((char *) (x)) + ((unsigned long) (y)))
|
||||
#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)
|
||||
static void *elfcorehdr_newmem;
|
||||
|
||||
/*
|
||||
* Copy one page from "oldmem"
|
||||
* Copy one page from zfcpdump "oldmem"
|
||||
*
|
||||
* For pages below ZFCPDUMP_HSA_SIZE memory from the HSA is copied. Otherwise
|
||||
* real memory copy is used.
|
||||
*/
|
||||
static ssize_t copy_oldmem_page_zfcpdump(char *buf, size_t csize,
|
||||
unsigned long src, int userbuf)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (src < ZFCPDUMP_HSA_SIZE) {
|
||||
rc = memcpy_hsa(buf, src, csize, userbuf);
|
||||
} else {
|
||||
if (userbuf)
|
||||
rc = copy_to_user_real((void __force __user *) buf,
|
||||
(void *) src, csize);
|
||||
else
|
||||
rc = memcpy_real(buf, (void *) src, csize);
|
||||
}
|
||||
return rc ? rc : csize;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy one page from kdump "oldmem"
|
||||
*
|
||||
* For the kdump reserved memory this functions performs a swap operation:
|
||||
* - [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE] is mapped to [0 - OLDMEM_SIZE].
|
||||
* - [0 - OLDMEM_SIZE] is mapped to [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE]
|
||||
*/
|
||||
ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
|
||||
size_t csize, unsigned long offset, int userbuf)
|
||||
static ssize_t copy_oldmem_page_kdump(char *buf, size_t csize,
|
||||
unsigned long src, int userbuf)
|
||||
|
||||
{
|
||||
unsigned long src;
|
||||
int rc;
|
||||
|
||||
if (!csize)
|
||||
return 0;
|
||||
|
||||
src = (pfn << PAGE_SHIFT) + offset;
|
||||
if (src < OLDMEM_SIZE)
|
||||
src += OLDMEM_BASE;
|
||||
else if (src > OLDMEM_BASE &&
|
||||
@ -95,17 +115,35 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
|
||||
(void *) src, csize);
|
||||
else
|
||||
rc = copy_page_real(buf, (void *) src, csize);
|
||||
return (rc == 0) ? csize : rc;
|
||||
return (rc == 0) ? rc : csize;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remap "oldmem"
|
||||
* Copy one page from "oldmem"
|
||||
*/
|
||||
ssize_t copy_oldmem_page(unsigned long pfn, char *buf, size_t csize,
|
||||
unsigned long offset, int userbuf)
|
||||
{
|
||||
unsigned long src;
|
||||
|
||||
if (!csize)
|
||||
return 0;
|
||||
src = (pfn << PAGE_SHIFT) + offset;
|
||||
if (OLDMEM_BASE)
|
||||
return copy_oldmem_page_kdump(buf, csize, src, userbuf);
|
||||
else
|
||||
return copy_oldmem_page_zfcpdump(buf, csize, src, userbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remap "oldmem" for kdump
|
||||
*
|
||||
* For the kdump reserved memory this functions performs a swap operation:
|
||||
* [0 - OLDMEM_SIZE] is mapped to [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE]
|
||||
*/
|
||||
int remap_oldmem_pfn_range(struct vm_area_struct *vma, unsigned long from,
|
||||
unsigned long pfn, unsigned long size, pgprot_t prot)
|
||||
static int remap_oldmem_pfn_range_kdump(struct vm_area_struct *vma,
|
||||
unsigned long from, unsigned long pfn,
|
||||
unsigned long size, pgprot_t prot)
|
||||
{
|
||||
unsigned long size_old;
|
||||
int rc;
|
||||
@ -124,6 +162,43 @@ int remap_oldmem_pfn_range(struct vm_area_struct *vma, unsigned long from,
|
||||
return remap_pfn_range(vma, from, pfn, size, prot);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remap "oldmem" for zfcpdump
|
||||
*
|
||||
* We only map available memory above ZFCPDUMP_HSA_SIZE. Memory below
|
||||
* ZFCPDUMP_HSA_SIZE is read on demand using the copy_oldmem_page() function.
|
||||
*/
|
||||
static int remap_oldmem_pfn_range_zfcpdump(struct vm_area_struct *vma,
|
||||
unsigned long from,
|
||||
unsigned long pfn,
|
||||
unsigned long size, pgprot_t prot)
|
||||
{
|
||||
unsigned long size_hsa;
|
||||
|
||||
if (pfn < ZFCPDUMP_HSA_SIZE >> PAGE_SHIFT) {
|
||||
size_hsa = min(size, ZFCPDUMP_HSA_SIZE - (pfn << PAGE_SHIFT));
|
||||
if (size == size_hsa)
|
||||
return 0;
|
||||
size -= size_hsa;
|
||||
from += size_hsa;
|
||||
pfn += size_hsa >> PAGE_SHIFT;
|
||||
}
|
||||
return remap_pfn_range(vma, from, pfn, size, prot);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remap "oldmem" for kdump or zfcpdump
|
||||
*/
|
||||
int remap_oldmem_pfn_range(struct vm_area_struct *vma, unsigned long from,
|
||||
unsigned long pfn, unsigned long size, pgprot_t prot)
|
||||
{
|
||||
if (OLDMEM_BASE)
|
||||
return remap_oldmem_pfn_range_kdump(vma, from, pfn, size, prot);
|
||||
else
|
||||
return remap_oldmem_pfn_range_zfcpdump(vma, from, pfn, size,
|
||||
prot);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy memory from old kernel
|
||||
*/
|
||||
@ -132,11 +207,21 @@ int copy_from_oldmem(void *dest, void *src, size_t count)
|
||||
unsigned long copied = 0;
|
||||
int rc;
|
||||
|
||||
if ((unsigned long) src < OLDMEM_SIZE) {
|
||||
copied = min(count, OLDMEM_SIZE - (unsigned long) src);
|
||||
rc = memcpy_real(dest, src + OLDMEM_BASE, copied);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (OLDMEM_BASE) {
|
||||
if ((unsigned long) src < OLDMEM_SIZE) {
|
||||
copied = min(count, OLDMEM_SIZE - (unsigned long) src);
|
||||
rc = memcpy_real(dest, src + OLDMEM_BASE, copied);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
if ((unsigned long) src < ZFCPDUMP_HSA_SIZE) {
|
||||
copied = min(count,
|
||||
ZFCPDUMP_HSA_SIZE - (unsigned long) src);
|
||||
rc = memcpy_hsa(dest, (unsigned long) src, copied, 0);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
return memcpy_real(dest + copied, src + copied, count - copied);
|
||||
}
|
||||
@ -466,7 +551,8 @@ int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size)
|
||||
u32 alloc_size;
|
||||
u64 hdr_off;
|
||||
|
||||
if (!OLDMEM_BASE)
|
||||
/* If we are not in kdump or zfcpdump mode return */
|
||||
if (!OLDMEM_BASE && ipl_info.type != IPL_TYPE_FCP_DUMP)
|
||||
return 0;
|
||||
/* If elfcorehdr= has been passed via cmdline, we use that one */
|
||||
if (elfcorehdr_addr != ELFCORE_ADDR_MAX)
|
||||
|
@ -30,8 +30,8 @@
|
||||
|
||||
#define TRACE(x...) debug_sprintf_event(zcore_dbf, 1, x)
|
||||
|
||||
#define TO_USER 0
|
||||
#define TO_KERNEL 1
|
||||
#define TO_USER 1
|
||||
#define TO_KERNEL 0
|
||||
#define CHUNK_INFO_SIZE 34 /* 2 16-byte char, each followed by blank */
|
||||
|
||||
enum arch_id {
|
||||
@ -73,7 +73,7 @@ static struct ipl_parameter_block *ipl_block;
|
||||
* @count: Size of buffer, which should be copied
|
||||
* @mode: Either TO_KERNEL or TO_USER
|
||||
*/
|
||||
static int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode)
|
||||
int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode)
|
||||
{
|
||||
int offs, blk_num;
|
||||
static char buf[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
|
||||
|
Loading…
Reference in New Issue
Block a user