Hello Vivek,
For s390 we want to use /proc/vmcore for our SCSI stand-alone
dump (zfcpdump). We have support where the first HSA_SIZE bytes are
saved into a hypervisor owned memory area (HSA) before the kdump
kernel is booted. When the kdump kernel starts, it is restricted
to use only HSA_SIZE bytes.
The advantages of this mechanism are:
* No crashkernel memory has to be defined in the old kernel.
* Early boot problems (before kexec_load has been done) can be dumped
* Non-Linux systems can be dumped.
We modify the s390 copy_oldmem_page() function to read from the HSA memory
if memory below HSA_SIZE bytes is requested.
Since we cannot use the kexec tool to load the kernel in this scenario,
we have to build the ELF header in the 2nd (kdump/new) kernel.
So with the following patch set we would like to introduce the new
function that the ELF header for /proc/vmcore can be created in the 2nd
kernel memory.
The following steps are done during zfcpdump execution:
1. Production system crashes
2. User boots a SCSI disk that has been prepared with the zfcpdump tool
3. Hypervisor saves CPU state of boot CPU and HSA_SIZE bytes of memory into HSA
4. Boot loader loads kernel into low memory area
5. Kernel boots and uses only HSA_SIZE bytes of memory
6. Kernel saves registers of non-boot CPUs
7. Kernel does memory detection for dump memory map
8. Kernel creates ELF header for /proc/vmcore
9. /proc/vmcore uses this header for initialization
10. The zfcpdump user space reads /proc/vmcore to write dump to SCSI disk
- copy_oldmem_page() copies from HSA for memory below HSA_SIZE
- copy_oldmem_page() copies from real memory for memory above HSA_SIZE
Jan Willeke (1):
s390/kdump: Use ELFCORE_ADDR_NEWMEM for zfcpdump
Michael Holzheu (3):
kdump: Introduce ELFCORE_ADDR_NEWMEM
s390/kdump: Use ELFCORE_ADDR_NEWMEM for kdump
kdump: Merge set_vmcore_list_offsets_elf64/elf32/newmem
arch/s390/Kconfig | 3 +-
arch/s390/include/asm/sclp.h | 1 +
arch/s390/kernel/crash_dump.c | 103 +++++++++++++++++++++++++++---------------
arch/s390/kernel/setup.c | 2 +-
drivers/s390/char/zcore.c | 6 +--
fs/proc/vmcore.c | 89 ++++++++++++++++++++++--------------
include/linux/crash_dump.h | 4 +-
7 files changed, 131 insertions(+), 77 deletions(-)
--
1.8.1.6
From: Jan Willeke <[email protected]>
This patch modifies the s390 copy_oldmem_page() function for zfcpdump
to read from the HSA memory if memory below HSA_SIZE bytes is requested.
Otherwise from real memory is read.
Signed-off-by: Jan Willeke <[email protected]>
Signed-off-by: Michael Holzheu <[email protected]>
---
arch/s390/Kconfig | 3 +-
arch/s390/include/asm/sclp.h | 1 +
arch/s390/kernel/crash_dump.c | 77 +++++++++++++++++++++++++++++++++----------
drivers/s390/char/zcore.c | 6 ++--
4 files changed, 65 insertions(+), 22 deletions(-)
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 2c9789d..a0d78f1 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -516,6 +516,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
@@ -526,7 +527,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.
diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h
index 06a1361..7dc7f9c 100644
--- a/arch/s390/include/asm/sclp.h
+++ b/arch/s390/include/asm/sclp.h
@@ -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 */
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c
index f1feaaa..1522dfc 100644
--- a/arch/s390/kernel/crash_dump.c
+++ b/arch/s390/kernel/crash_dump.c
@@ -16,27 +16,40 @@
#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)))
#define PTR_DIFF(x, y) ((unsigned long)(((char *) (x)) - ((unsigned long) (y))))
/*
- * Copy one page from "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)
+{
+ if (src < ZFCPDUMP_HSA_SIZE) {
+ if (memcpy_hsa(buf, src, csize, userbuf) < 0)
+ return -EINVAL;
+ } else {
+ if (userbuf)
+ copy_to_user_real((void __force __user *) buf,
+ (void *) src, csize);
+ else
+ memcpy_real(buf, (void *) src, csize);
+ }
+ return csize;
+}
+
+/*
* 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;
-
- if (!csize)
- return 0;
-
- src = (pfn << PAGE_SHIFT) + offset;
if (src < OLDMEM_SIZE)
src += OLDMEM_BASE;
else if (src > OLDMEM_BASE &&
@@ -51,6 +64,23 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
}
/*
+ * 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);
+}
+
+/*
* Copy memory from old kernel
*/
int copy_from_oldmem(void *dest, void *src, size_t count)
@@ -58,11 +88,20 @@ 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);
}
@@ -418,12 +457,14 @@ int arch_vmcore_get_elf_hdr(char **elfcorebuf, size_t *elfcorebuf_sz)
/*
* Create kdump ELF core header in new kernel, if it has not been passed via
- * the "elfcorehdr" kernel parameter
+ * the "elfcorehdr" kernel parameter or if we run as zfcpdump.
*/
static int setup_kdump_elfcorehdr(void)
{
- if (!OLDMEM_BASE || is_kdump_kernel())
- return -EINVAL;
+ if (!OLDMEM_BASE && (ipl_info.type != IPL_TYPE_FCP_DUMP))
+ return -EINVAL; /* No kdump and no zfcpdump */
+ if (is_kdump_kernel())
+ return -EINVAL; /* "elfcorehdr=" has been set by kexec */
elfcorehdr_addr = ELFCORE_ADDR_NEWMEM;
return 0;
}
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 2282061..e1e1663 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -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)));
--
1.8.1.6
Currently for s390 we create the ELF core header in the 2nd kernel
with a small trick. We relocate the addresses in the ELF header in
a way that for the /proc/vmcore code it seems to be in the 1st kernel
(old) memory and the read_from_oldmem() returns the correct data.
This allows the /proc/vmcore code to use the ELF header in the
2nd kernel.
This patch now exchanges the old mechanism with the new and much
cleaner ELFCORE_ADDR_NEWMEM feature that now offcially allows to
create the ELF core header in the 2nd kernel.
Signed-off-by: Michael Holzheu <[email protected]>
---
arch/s390/kernel/crash_dump.c | 26 +++++++-------------------
arch/s390/kernel/setup.c | 2 +-
2 files changed, 8 insertions(+), 20 deletions(-)
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c
index fb8d878..f1feaaa 100644
--- a/arch/s390/kernel/crash_dump.c
+++ b/arch/s390/kernel/crash_dump.c
@@ -325,14 +325,6 @@ static int get_mem_chunk_cnt(void)
}
/*
- * Relocate pointer in order to allow vmcore code access the data
- */
-static inline unsigned long relocate(unsigned long addr)
-{
- return OLDMEM_BASE + addr;
-}
-
-/*
* Initialize ELF loads (new kernel)
*/
static int loads_init(Elf64_Phdr *phdr, u64 loads_offset)
@@ -383,7 +375,7 @@ static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)
ptr = nt_vmcoreinfo(ptr);
memset(phdr, 0, sizeof(*phdr));
phdr->p_type = PT_NOTE;
- phdr->p_offset = relocate(notes_offset);
+ phdr->p_offset = notes_offset;
phdr->p_filesz = (unsigned long) PTR_SUB(ptr, ptr_start);
phdr->p_memsz = phdr->p_filesz;
return ptr;
@@ -392,7 +384,7 @@ static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)
/*
* Create ELF core header (new kernel)
*/
-static void s390_elf_corehdr_create(char **elfcorebuf, size_t *elfcorebuf_sz)
+int arch_vmcore_get_elf_hdr(char **elfcorebuf, size_t *elfcorebuf_sz)
{
Elf64_Phdr *phdr_notes, *phdr_loads;
int mem_chunk_cnt;
@@ -414,13 +406,14 @@ static void s390_elf_corehdr_create(char **elfcorebuf, size_t *elfcorebuf_sz)
ptr = PTR_ADD(ptr, sizeof(Elf64_Phdr) * mem_chunk_cnt);
/* Init notes */
hdr_off = PTR_DIFF(ptr, hdr);
- ptr = notes_init(phdr_notes, ptr, ((unsigned long) hdr) + hdr_off);
+ ptr = notes_init(phdr_notes, ptr, hdr_off);
/* Init loads */
hdr_off = PTR_DIFF(ptr, hdr);
- loads_init(phdr_loads, ((unsigned long) hdr) + hdr_off);
+ loads_init(phdr_loads, hdr_off);
*elfcorebuf_sz = hdr_off;
- *elfcorebuf = (void *) relocate((unsigned long) hdr);
+ *elfcorebuf = hdr;
BUG_ON(*elfcorebuf_sz > alloc_size);
+ return 0;
}
/*
@@ -429,14 +422,9 @@ static void s390_elf_corehdr_create(char **elfcorebuf, size_t *elfcorebuf_sz)
*/
static int setup_kdump_elfcorehdr(void)
{
- size_t elfcorebuf_sz;
- char *elfcorebuf;
-
if (!OLDMEM_BASE || is_kdump_kernel())
return -EINVAL;
- s390_elf_corehdr_create(&elfcorebuf, &elfcorebuf_sz);
- elfcorehdr_addr = (unsigned long long) elfcorebuf;
- elfcorehdr_size = elfcorebuf_sz;
+ elfcorehdr_addr = ELFCORE_ADDR_NEWMEM;
return 0;
}
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 0f419c5..86f2ca1 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -889,7 +889,7 @@ static void __init setup_memory(void)
reserve_bootmem(crashk_res.start,
crashk_res.end - crashk_res.start + 1,
BOOTMEM_DEFAULT);
- if (is_kdump_kernel())
+ if (is_kdump_kernel() && (elfcorehdr_addr != ELFCORE_ADDR_NEWMEM))
reserve_bootmem(elfcorehdr_addr - OLDMEM_BASE,
PAGE_ALIGN(elfcorehdr_size), BOOTMEM_DEFAULT);
#endif
--
1.8.1.6
Currently vmcore gets the ELF header from oldmem using the global variable
"elfcorehdr_addr". This patch introduces a new possible value
ELFCORE_ADDR_NEWMEM. This indicates that the ELF header is allocated
in the new (2nd) kernel. In this case a new architecture function
arch_vmcore_get_elf_hdr() is called to obtain address and length of the
ELF header. The ELF header that is created in the 2nd kernel already
contains the correct relative offsets in the ELF notes and loads sections.
Signed-off-by: Michael Holzheu <[email protected]>
---
fs/proc/vmcore.c | 65 ++++++++++++++++++++++++++++++++++++++++++++--
include/linux/crash_dump.h | 4 ++-
2 files changed, 66 insertions(+), 3 deletions(-)
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
index 17f7e08..71db4e6 100644
--- a/fs/proc/vmcore.c
+++ b/fs/proc/vmcore.c
@@ -487,6 +487,18 @@ static int __init process_ptload_program_headers_elf32(char *elfptr,
}
/* Sets offset fields of vmcore elements. */
+static void __init set_vmcore_list_offsets_newmem(struct list_head *vc_list)
+{
+ loff_t vmcore_off = elfcorebuf_sz;
+ struct vmcore *m;
+
+ list_for_each_entry(m, vc_list, list) {
+ m->offset = vmcore_off;
+ vmcore_off += m->size;
+ }
+}
+
+/* Sets offset fields of vmcore elements. */
static void __init set_vmcore_list_offsets_elf64(char *elfptr,
struct list_head *vc_list)
{
@@ -636,7 +648,7 @@ static int __init parse_crash_elf32_headers(void)
return 0;
}
-static int __init parse_crash_elf_headers(void)
+static int __init parse_crash_elf_headers_oldmem(void)
{
unsigned char e_ident[EI_NIDENT];
u64 addr;
@@ -672,6 +684,52 @@ static int __init parse_crash_elf_headers(void)
return 0;
}
+/*
+ * provide an empty default implementation here -- architecture
+ * code may override this
+ */
+int __weak arch_vmcore_get_elf_hdr(char **elfcorebuf, size_t *elfcorebuf_sz)
+{
+ return -EOPNOTSUPP;
+}
+
+static int parse_crash_elf_headers_newmem(void)
+{
+ unsigned char e_ident[EI_NIDENT];
+ int rc;
+
+ rc = arch_vmcore_get_elf_hdr(&elfcorebuf, &elfcorebuf_sz);
+ if (rc)
+ return rc;
+ memcpy(e_ident, elfcorebuf, EI_NIDENT);
+ if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) {
+ pr_warn("Warning: Core image elf header not found\n");
+ rc = -EINVAL;
+ goto fail;
+ }
+ if (e_ident[EI_CLASS] == ELFCLASS64) {
+ rc = process_ptload_program_headers_elf64(elfcorebuf,
+ elfcorebuf_sz,
+ &vmcore_list);
+ if (rc)
+ goto fail;
+ set_vmcore_list_offsets_newmem(&vmcore_list);
+ vmcore_size = get_vmcore_size_elf64(elfcorebuf);
+ } else if (e_ident[EI_CLASS] == ELFCLASS32) {
+ rc = process_ptload_program_headers_elf32(elfcorebuf,
+ elfcorebuf_sz,
+ &vmcore_list);
+ if (rc)
+ goto fail;
+ set_vmcore_list_offsets_newmem(&vmcore_list);
+ vmcore_size = get_vmcore_size_elf32(elfcorebuf);
+ }
+ return 0;
+fail:
+ kfree(elfcorebuf);
+ return rc;
+}
+
/* Init function for vmcore module. */
static int __init vmcore_init(void)
{
@@ -680,7 +738,10 @@ static int __init vmcore_init(void)
/* If elfcorehdr= has been passed in cmdline, then capture the dump.*/
if (!(is_vmcore_usable()))
return rc;
- rc = parse_crash_elf_headers();
+ if (elfcorehdr_addr == ELFCORE_ADDR_NEWMEM)
+ rc = parse_crash_elf_headers_newmem();
+ else
+ rc = parse_crash_elf_headers_oldmem();
if (rc) {
pr_warn("Kdump: vmcore not initialized\n");
return rc;
diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h
index 37e4f8d..9424d4fc 100644
--- a/include/linux/crash_dump.h
+++ b/include/linux/crash_dump.h
@@ -8,10 +8,12 @@
#define ELFCORE_ADDR_MAX (-1ULL)
#define ELFCORE_ADDR_ERR (-2ULL)
+#define ELFCORE_ADDR_NEWMEM (-3ULL)
extern unsigned long long elfcorehdr_addr;
extern unsigned long long elfcorehdr_size;
-
+extern int arch_vmcore_get_elf_hdr(char **elfcorebuf,
+ size_t *elfcorebuf_sz);
extern ssize_t copy_oldmem_page(unsigned long, char *, size_t,
unsigned long, int);
--
1.8.1.6
The three functions set_vmcore_list_offsets_elf64(),
set_vmcore_list_offsets_elf32(), and set_vmcore_list_offsets_newmem()
can be merged to a single fuction set_vmcore_list_offsets()
Signed-off-by: Michael Holzheu <[email protected]>
---
fs/proc/vmcore.c | 50 +++++---------------------------------------------
1 file changed, 5 insertions(+), 45 deletions(-)
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
index 71db4e6..3ddfc73 100644
--- a/fs/proc/vmcore.c
+++ b/fs/proc/vmcore.c
@@ -487,7 +487,7 @@ static int __init process_ptload_program_headers_elf32(char *elfptr,
}
/* Sets offset fields of vmcore elements. */
-static void __init set_vmcore_list_offsets_newmem(struct list_head *vc_list)
+static void __init set_vmcore_list_offsets(struct list_head *vc_list)
{
loff_t vmcore_off = elfcorebuf_sz;
struct vmcore *m;
@@ -498,46 +498,6 @@ static void __init set_vmcore_list_offsets_newmem(struct list_head *vc_list)
}
}
-/* Sets offset fields of vmcore elements. */
-static void __init set_vmcore_list_offsets_elf64(char *elfptr,
- struct list_head *vc_list)
-{
- loff_t vmcore_off;
- Elf64_Ehdr *ehdr_ptr;
- struct vmcore *m;
-
- ehdr_ptr = (Elf64_Ehdr *)elfptr;
-
- /* Skip Elf header and program headers. */
- vmcore_off = sizeof(Elf64_Ehdr) +
- (ehdr_ptr->e_phnum) * sizeof(Elf64_Phdr);
-
- list_for_each_entry(m, vc_list, list) {
- m->offset = vmcore_off;
- vmcore_off += m->size;
- }
-}
-
-/* Sets offset fields of vmcore elements. */
-static void __init set_vmcore_list_offsets_elf32(char *elfptr,
- struct list_head *vc_list)
-{
- loff_t vmcore_off;
- Elf32_Ehdr *ehdr_ptr;
- struct vmcore *m;
-
- ehdr_ptr = (Elf32_Ehdr *)elfptr;
-
- /* Skip Elf header and program headers. */
- vmcore_off = sizeof(Elf32_Ehdr) +
- (ehdr_ptr->e_phnum) * sizeof(Elf32_Phdr);
-
- list_for_each_entry(m, vc_list, list) {
- m->offset = vmcore_off;
- vmcore_off += m->size;
- }
-}
-
static int __init parse_crash_elf64_headers(void)
{
int rc=0;
@@ -589,7 +549,7 @@ static int __init parse_crash_elf64_headers(void)
kfree(elfcorebuf);
return rc;
}
- set_vmcore_list_offsets_elf64(elfcorebuf, &vmcore_list);
+ set_vmcore_list_offsets(&vmcore_list);
return 0;
}
@@ -644,7 +604,7 @@ static int __init parse_crash_elf32_headers(void)
kfree(elfcorebuf);
return rc;
}
- set_vmcore_list_offsets_elf32(elfcorebuf, &vmcore_list);
+ set_vmcore_list_offsets(&vmcore_list);
return 0;
}
@@ -713,7 +673,7 @@ static int parse_crash_elf_headers_newmem(void)
&vmcore_list);
if (rc)
goto fail;
- set_vmcore_list_offsets_newmem(&vmcore_list);
+ set_vmcore_list_offsets(&vmcore_list);
vmcore_size = get_vmcore_size_elf64(elfcorebuf);
} else if (e_ident[EI_CLASS] == ELFCLASS32) {
rc = process_ptload_program_headers_elf32(elfcorebuf,
@@ -721,7 +681,7 @@ static int parse_crash_elf_headers_newmem(void)
&vmcore_list);
if (rc)
goto fail;
- set_vmcore_list_offsets_newmem(&vmcore_list);
+ set_vmcore_list_offsets(&vmcore_list);
vmcore_size = get_vmcore_size_elf32(elfcorebuf);
}
return 0;
--
1.8.1.6
On Mon, May 06, 2013 at 03:09:55PM +0200, Michael Holzheu wrote:
> Hello Vivek,
>
> For s390 we want to use /proc/vmcore for our SCSI stand-alone
> dump (zfcpdump). We have support where the first HSA_SIZE bytes are
> saved into a hypervisor owned memory area (HSA) before the kdump
> kernel is booted. When the kdump kernel starts, it is restricted
> to use only HSA_SIZE bytes.
>
Hi Michael,
Hatayama is changing /proc/vmcore interface to support mmap(). Can you
please rebase your changes on top of those patches.
http://thread.gmane.org/gmane.linux.kernel/1477622
Secondly, I think /proc/vmcore does not have to know whether elf
headers are in old memory or new memory. Given that s390 is taking
a deviation, so it now becomes an arch specific detail. Can't we
just create few arch specific helper functions to retrieve and free
elf headers.
- arch_get_crash_headers()
- All arch except return elfcorehdr_add except s390.
- arch_read_crash_header_data()
- All arch just call into read_from_oldmem() except s390. We
can provide a generic implementation in /proc/vmcore.c so
all other arch can use that generic implementation. Or
use symbol override trick.
- arch_free_crash_headers()
- All arch do nothing except s390 which can reclaim the memory
for elf headers prepared. Generic code has parsed/copied the
headers by now.
What do you think? Above 3 calls should solve the problem and allow
arch to handle elf headers differently. And generic implementation
still keeps common logic for processing headers.
Thanks
Vivek
Hello Vivek,
On Tue, 7 May 2013 12:37:01 -0400
Vivek Goyal <[email protected]> wrote:
> On Mon, May 06, 2013 at 03:09:55PM +0200, Michael Holzheu wrote:
> > Hello Vivek,
> >
> > For s390 we want to use /proc/vmcore for our SCSI stand-alone
> > dump (zfcpdump). We have support where the first HSA_SIZE bytes are
> > saved into a hypervisor owned memory area (HSA) before the kdump
> > kernel is booted. When the kdump kernel starts, it is restricted
> > to use only HSA_SIZE bytes.
> >
>
> Hi Michael,
>
> Hatayama is changing /proc/vmcore interface to support mmap(). Can you
> please rebase your changes on top of those patches.
>
> http://thread.gmane.org/gmane.linux.kernel/1477622
Fine, we will do that.
> Secondly, I think /proc/vmcore does not have to know whether elf
> headers are in old memory or new memory. Given that s390 is taking
> a deviation, so it now becomes an arch specific detail. Can't we
> just create few arch specific helper functions to retrieve and free
> elf headers.
>
> - arch_get_crash_headers()
> - All arch except return elfcorehdr_add except s390.
> - arch_read_crash_header_data()
> - All arch just call into read_from_oldmem() except s390. We
> can provide a generic implementation in /proc/vmcore.c so
> all other arch can use that generic implementation. Or
> use symbol override trick.
> - arch_free_crash_headers()
> - All arch do nothing except s390 which can reclaim the memory
> for elf headers prepared. Generic code has parsed/copied
> the headers by now.
>
> What do you think? Above 3 calls should solve the problem and allow
> arch to handle elf headers differently. And generic implementation
> still keeps common logic for processing headers.
Ok, we will try that. There might be a problem that our ELF notes
content is also in the new kernel memory. But also for that there be a
solution.
Michael