Skip to contentSkip to conversation

kdump: Patch series for s390 support (version 3)

PATCH In review Michael Holzheu 3 participants 20 messages Aug 12, 2011 – Aug 19, 2011

Subsystems (8)
lore
Share & tools
lore
#0 lore raw

v3 cover kdump: Patch series for s390 support (version 3)

Hello Vivek,

I updated the patch series according to our last discussions. As you requested, I removed the "#if !defined(CONFIG_S390)" in the panic function.

The semantics is now as follows:

If kdump is loaded, kdump is always triggered for panic and PSW restart (s390 NMI). If kdump is not loaded, the s390 shutdown actions defined under /sys/firmware are executed as we are doing it already today.

I also added again patches for stand-alone dump integration:

For s390 we add a parameter to the purgatory entry point. When "0" is passed, purgatory only returns the result of the checksum test. When "1" is passed, purgatory triggers kdump. So we call purgatory twice. First for checking and second time for execution. You can argue that it would be better to call purgatory only once and it returns only, if checksums are invalid. Unfortunately this would be very hard to implement for us, because we switch to the boot CPU before kdump is finally triggered and after that currently it is not possible to return from the called function.

panic --------+

              +--- crash_kexec()
              |    call_s390_shutdown_actions() -> stand-alone dump

PSW restart --+

crash_kexec +--> kdump loaded? --> machine_kexec()

            |
            +--> kdump not loaded --> return

machine_kexec +-> purgatory(0)==0 -> switch to IPL cpu -> purgatory(1) -> kdump

              |
              +-> purgatory(0)!=0 -> return

See patches [6] and [8] for details.

Does that sound ok for you?

Michael

Patch overview:
---------------
[1-3] common code changes (could you please ACC patches [1] and [3]?)

[4]   s390 kdump preparation patch
[5]   s390 kdump backend
[6]   s390 stand-alone dump/shutdown actions integration
[7]   kexec-tools: s390 kdump backend for kexec-tools
[8]   kexec-tools: s390 stand-alone dump/shutdown actions integration

History: v1->v2:
----------------
Main changes compared to version 1:
1. We use purgatory code
2. We use pre-allocated ELF core header
3. Registers are saved in old kernel
4. Removed meminfo

#1 lore raw

PATCH v3 1/8 kdump: Add KEXEC_CRASH_CONTROL_MEMORY_LIMIT

From: Michael Holzheu <[email protected]>

On s390 there is a different KEXEC_CONTROL_MEMORY_LIMIT for the normal and the kdump kexec case. Therefore this patch introduces a new macro KEXEC_CRASH_CONTROL_MEMORY_LIMIT. This is set to KEXEC_CONTROL_MEMORY_LIMIT for all architectures that do not define KEXEC_CRASH_CONTROL_MEMORY_LIMIT.

---
 include/linux/kexec.h |    4 ++++
 kernel/kexec.c        |    2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)
include/linux/kexec.h +4 -0
@@ -33,6 +33,10 @@
 #error KEXEC_ARCH not defined
 #endif
 
+#ifndef KEXEC_CRASH_CONTROL_MEMORY_LIMIT
+#define KEXEC_CRASH_CONTROL_MEMORY_LIMIT KEXEC_CONTROL_MEMORY_LIMIT
+#endif
+
 #define KEXEC_NOTE_HEAD_BYTES ALIGN(sizeof(struct elf_note), 4)
 #define KEXEC_CORE_NOTE_NAME "CORE"
 #define KEXEC_CORE_NOTE_NAME_BYTES ALIGN(sizeof(KEXEC_CORE_NOTE_NAME), 4)
kernel/kexec.c +1 -1
@@ -498,7 +498,7 @@ static struct page *kimage_alloc_crash_c
 	while (hole_end <= crashk_res.end) {
 		unsigned long i;
 
-		if (hole_end > KEXEC_CONTROL_MEMORY_LIMIT)
+		if (hole_end > KEXEC_CRASH_CONTROL_MEMORY_LIMIT)
 			break;
 		if (hole_end > crashk_res.end)
 			break;
#2 lore raw

PATCH v3 2/8 kdump: Make kimage_load_crash_segment() weak

In reply to Michael Holzheu

From: Michael Holzheu <[email protected]>

On s390 we do not create page tables at all for the crashkernel memory. This requires a s390 specific version for kimage_load_crash_segment(). Therefore this patch declares this function as "__weak". The s390 version is very simple. It just copies the kexec segment to real memory without using page tables:

int kimage_load_crash_segment(struct kimage *image,
struct kexec_segment *segment)

{
        return copy_from_user_real((void *) segment->mem, segment->buf,
                                   segment->bufsz);
}

There are two main advantages of not creating page tables for the crashkernel memory:

a) It saves memory. We have scenarios in mind, where crashkernel memory can be very large and saving page table space is important.
b) We protect the crashkernel memory from being overwritten.

---
 kernel/kexec.c |    9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
kernel/kexec.c +7 -2
@@ -842,8 +842,13 @@ out:
 	return result;
 }
 
-static int kimage_load_crash_segment(struct kimage *image,
-					struct kexec_segment *segment)
+/*
+ * Load crash segment into memory. Architecture code can override this
+ * function. E.g. this is necessary for architectures that do not
+ * create page tables for crashkernel memory.
+ */
+int __weak kimage_load_crash_segment(struct kimage *image,
+				     struct kexec_segment *segment)
 {
 	/* For crash dumps kernels we simply copy the data from
 	 * user space to it's destination.
#3 lore raw

Re: [patch v3 2/8] kdump: Make kimage_load_crash_segment() weak

Quoted 15 lines · Michael Holzheu

From: Michael Holzheu <[email protected]>

On s390 we do not create page tables at all for the crashkernel memory. This requires a s390 specific version for kimage_load_crash_segment(). Therefore this patch declares this function as "__weak". The s390 version is very simple. It just copies the kexec segment to real memory without using page tables:

int kimage_load_crash_segment(struct kimage *image,
struct kexec_segment *segment)

{
        return copy_from_user_real((void *) segment->mem, segment->buf,
                                   segment->bufsz);
}
Quoted 6 lines

There are two main advantages of not creating page tables for the crashkernel memory:

a) It saves memory. We have scenarios in mind, where crashkernel memory can be very large and saving page table space is important.
b) We protect the crashkernel memory from being overwritten.

Michael,

Thinking more about it. Can't we provide a arch specific version of kmap() and kunmap() so that we create temporary mappings to copy the pages and then these are torn off. That way you don't waste space as well you don't have the risk of overwritting the loaded kernel.

Exporting the knowledge of generic kexec segments to arch code sounds like little odd choice.

Thanks
Vivek

#4 lore raw

Re: [patch v3 2/8] kdump: Make kimage_load_crash_segment() weak

Hello Vivek,

Quoted 23 lines · Vivek Goyal
Quoted 15 lines · Michael Holzheu

From: Michael Holzheu <[email protected]>

On s390 we do not create page tables at all for the crashkernel memory. This requires a s390 specific version for kimage_load_crash_segment(). Therefore this patch declares this function as "__weak". The s390 version is very simple. It just copies the kexec segment to real memory without using page tables:

int kimage_load_crash_segment(struct kimage *image,
struct kexec_segment *segment)

{
        return copy_from_user_real((void *) segment->mem, segment->buf,
                                   segment->bufsz);
}
Quoted 6 lines

There are two main advantages of not creating page tables for the crashkernel memory:

a) It saves memory. We have scenarios in mind, where crashkernel memory can be very large and saving page table space is important.
b) We protect the crashkernel memory from being overwritten.

Quoted 5 lines

Michael,

Thinking more about it. Can't we provide a arch specific version of kmap() and kunmap() so that we create temporary mappings to copy the pages and then these are torn off.

Isn't kmap/kunmap() used for higmem? These functions are called from many different functions in the Linux kernel, not only for kdump. I would assume that creating and removing mappings with these functions is not what a caller would expect and probably would break the Linux kernel at many other places, no?

Perhaps we can finish this discussion after my vacation. I will change my patch series that we even do not need this patch...

So only two common code patches are remaining. I will send the common code patches again and will ask Andrew Morton to integrate them in the next merge window. The s390 patches will be integrated by Martin.

Michael

#5 lore raw

Re: [patch v3 2/8] kdump: Make kimage_load_crash_segment() weak

Quoted 32 lines · Michael Holzheu

Hello Vivek,

Quoted 23 lines · Vivek Goyal
Quoted 15 lines · Michael Holzheu

From: Michael Holzheu <[email protected]>

On s390 we do not create page tables at all for the crashkernel memory. This requires a s390 specific version for kimage_load_crash_segment(). Therefore this patch declares this function as "__weak". The s390 version is very simple. It just copies the kexec segment to real memory without using page tables:

int kimage_load_crash_segment(struct kimage *image,
struct kexec_segment *segment)

{
        return copy_from_user_real((void *) segment->mem, segment->buf,
                                   segment->bufsz);
}
Quoted 6 lines

There are two main advantages of not creating page tables for the crashkernel memory:

a) It saves memory. We have scenarios in mind, where crashkernel memory can be very large and saving page table space is important.
b) We protect the crashkernel memory from being overwritten.

Quoted 5 lines

Michael,

Thinking more about it. Can't we provide a arch specific version of kmap() and kunmap() so that we create temporary mappings to copy the pages and then these are torn off.

Quoted 5 lines

Isn't kmap/kunmap() used for higmem? These functions are called from many different functions in the Linux kernel, not only for kdump. I would assume that creating and removing mappings with these functions is not what a caller would expect and probably would break the Linux kernel at many other places, no?

[CCing linux-mm]

Yes it is being used for highmem pages. If arch has not defined kmap() then generic definition is just returning page_address(page), expecting that page will be mapped.

I was wondering that what will be broken if arch decides to extend this to create temporary mappings for pages which are not HIGHMEM but do not have any mapping. (Like this special case of s390).

I guess memory management guys can give a better answer here. As a layman, kmap() seems to be the way to get a kernel mapping for any page frame and if one is not already there, then arch might create one on the fly, like we do for HIGHMEM pages. So the question is can be extend this to also cover pages which are not highmem but do not have any mappings on s390.

Quoted 3 lines

Perhaps we can finish this discussion after my vacation. I will change my patch series that we even do not need this patch...

So how are you planning to get rid of this patch without modifying kmap(), kunmap() implementation for s390?

Quoted 4 lines

So only two common code patches are remaining. I will send the common code patches again and will ask Andrew Morton to integrate them in the next merge window.The s390 patches will be integrated by Martin.

I am fine with merge of other 2 common patches. Once you repost the series, I will ack those.

Thanks
Vivek

#6 lore raw

Re: [patch v3 2/8] kdump: Make kimage_load_crash_segment() weak

Hello Vivek,

On Fri, 2011-08-19 at 09:48 -0400, Vivek Goyal wrote:

[snip]

Quoted 14 lines
Quoted 11 lines
Quoted 5 lines

Michael,

Thinking more about it. Can't we provide a arch specific version of kmap() and kunmap() so that we create temporary mappings to copy the pages and then these are torn off.

Isn't kmap/kunmap() used for higmem? These functions are called from many different functions in the Linux kernel, not only for kdump. I would assume that creating and removing mappings with these functions is not what a caller would expect and probably would break the Linux kernel at many other places, no?

[CCing linux-mm]

Quoted 7 lines

Yes it is being used for highmem pages. If arch has not defined kmap() then generic definition is just returning page_address(page), expecting that page will be mapped.

I was wondering that what will be broken if arch decides to extend this to create temporary mappings for pages which are not HIGHMEM but do not have any mapping. (Like this special case of s390).

At least we have significant additional overhead for all the other places where kmap/kunmap is called.

Quoted 8 lines

I guess memory management guys can give a better answer here. As a layman, kmap() seems to be the way to get a kernel mapping for any page frame and if one is not already there, then arch might create one on the fly, like we do for HIGHMEM pages. So the question is can be extend this to also cover pages which are not highmem but do not have any mappings on s390.

Quoted 1 line
Quoted 5 lines
Quoted 2 lines

Perhaps we can finish this discussion after my vacation. I will change my patch series that we even do not need this patch...

So how are you planning to get rid of this patch without modifying kmap(), kunmap() implementation for s390?

I will update my patch series that we do not remove page tables for crashkernel memory. So everything will be as on other architectures.

I hope that we can find a good solution after my vacation. Perhaps then I have enough energy again :-)

Quoted 6 lines
Quoted 3 lines

So only two common code patches are remaining. I will send the common code patches again and will ask Andrew Morton to integrate them in the next merge window.The s390 patches will be integrated by Martin.

I am fine with merge of other 2 common patches. Once you repost the series, I will ack those.

Great! I will resend the patches and contact Andrew Morton.

Thanks!

Michael

#7 lore raw

Re: [patch v3 2/8] kdump: Make kimage_load_crash_segment() weak

In reply to Vivek Goyal
Quoted 49 lines · On Fri, 19 Aug 2011 09:48:36 -0400 Vivek Goyal <[email protected]> wrote:
Quoted 32 lines · Michael Holzheu

Hello Vivek,

Quoted 23 lines · Vivek Goyal
Quoted 15 lines · Michael Holzheu

From: Michael Holzheu <[email protected]>

On s390 we do not create page tables at all for the crashkernel memory. This requires a s390 specific version for kimage_load_crash_segment(). Therefore this patch declares this function as "__weak". The s390 version is very simple. It just copies the kexec segment to real memory without using page tables:

int kimage_load_crash_segment(struct kimage *image,
struct kexec_segment *segment)

{
        return copy_from_user_real((void *) segment->mem, segment->buf,
                                   segment->bufsz);
}
Quoted 6 lines

There are two main advantages of not creating page tables for the crashkernel memory:

a) It saves memory. We have scenarios in mind, where crashkernel memory can be very large and saving page table space is important.
b) We protect the crashkernel memory from being overwritten.

Quoted 5 lines

Michael,

Thinking more about it. Can't we provide a arch specific version of kmap() and kunmap() so that we create temporary mappings to copy the pages and then these are torn off.

Quoted 5 lines

Isn't kmap/kunmap() used for higmem? These functions are called from many different functions in the Linux kernel, not only for kdump. I would assume that creating and removing mappings with these functions is not what a caller would expect and probably would break the Linux kernel at many other places, no?

[CCing linux-mm]

Yes it is being used for highmem pages. If arch has not defined kmap() then generic definition is just returning page_address(page), expecting that page will be mapped.

I was wondering that what will be broken if arch decides to extend this to create temporary mappings for pages which are not HIGHMEM but do not have any mapping. (Like this special case of s390).

Quoted 6 lines

I guess memory management guys can give a better answer here. As a layman, kmap() seems to be the way to get a kernel mapping for any page frame and if one is not already there, then arch might create one on the fly, like we do for HIGHMEM pages. So the question is can be extend this to also cover pages which are not highmem but do not have any mappings on s390.

Imho it would be wrong to misuse kmap/kunmap to get around a minor problem with the memory for the crash kernel. These functions are used to provide accessibility to highmem pages in the kernel address space. The highmem area is "normal" memory with corresponding struct page elements (the functions do take a struct page * as argument after all). They are not usable to map arbitrary page frames.

And we definitely don't want to make the memory management any slower by defining non-trivial kmap/kunmap functions.

Signature · 4 lines
blue skies,
   Martin.

"Reality continues to ruin my life." - Calvin.
#8 lore raw

Re: [patch v3 2/8] kdump: Make kimage_load_crash_segment() weak

Quoted 59 lines · Martin Schwidefsky
Quoted 49 lines · On Fri, 19 Aug 2011 09:48:36 -0400 Vivek Goyal <[email protected]> wrote:
Quoted 32 lines · Michael Holzheu

Hello Vivek,

Quoted 23 lines · Vivek Goyal
Quoted 15 lines · Michael Holzheu

From: Michael Holzheu <[email protected]>

On s390 we do not create page tables at all for the crashkernel memory. This requires a s390 specific version for kimage_load_crash_segment(). Therefore this patch declares this function as "__weak". The s390 version is very simple. It just copies the kexec segment to real memory without using page tables:

int kimage_load_crash_segment(struct kimage *image,
struct kexec_segment *segment)

{
        return copy_from_user_real((void *) segment->mem, segment->buf,
                                   segment->bufsz);
}
Quoted 6 lines

There are two main advantages of not creating page tables for the crashkernel memory:

a) It saves memory. We have scenarios in mind, where crashkernel memory can be very large and saving page table space is important.
b) We protect the crashkernel memory from being overwritten.

Quoted 5 lines

Michael,

Thinking more about it. Can't we provide a arch specific version of kmap() and kunmap() so that we create temporary mappings to copy the pages and then these are torn off.

Quoted 5 lines

Isn't kmap/kunmap() used for higmem? These functions are called from many different functions in the Linux kernel, not only for kdump. I would assume that creating and removing mappings with these functions is not what a caller would expect and probably would break the Linux kernel at many other places, no?

[CCing linux-mm]

Yes it is being used for highmem pages. If arch has not defined kmap() then generic definition is just returning page_address(page), expecting that page will be mapped.

I was wondering that what will be broken if arch decides to extend this to create temporary mappings for pages which are not HIGHMEM but do not have any mapping. (Like this special case of s390).

Quoted 6 lines

I guess memory management guys can give a better answer here. As a layman, kmap() seems to be the way to get a kernel mapping for any page frame and if one is not already there, then arch might create one on the fly, like we do for HIGHMEM pages. So the question is can be extend this to also cover pages which are not highmem but do not have any mappings on s390.

Quoted 6 lines

Imho it would be wrong to misuse kmap/kunmap to get around a minor problem with the memory for the crash kernel. These functions are used to provide accessibility to highmem pages in the kernel address space. The highmem area is "normal" memory with corresponding struct page elements (the functions do take a struct page * as argument after all). They are not usable to map arbitrary page frames.

Same is the case with crashkernel memory in s390 where these are normal pages, just that these are not mapped in linearly mapped region.

The only exception to highmem pages is that linearly mapped region is not big enough in certain arches, so we left them unmapped.

Quoted 3 lines

And we definitely don't want to make the memory management any slower by defining non-trivial kmap/kunmap functions.

if we continue to return page_address() and only go into else loop if page is not mapped, then there should not be any slow down for exisitng cases where memory is mapped?

Anyway, this was just a thought. I am not too particular about it and michael has agreed to get rid of code which was removing mappings for crashkernel area. So for the time we don't need above.

Thanks
Vivek

#9 lore raw

Re: [patch v3 2/8] kdump: Make kimage_load_crash_segment() weak

Quoted 67 lines · On Fri, 19 Aug 2011 10:37:48 -0400 Vivek Goyal <[email protected]> wrote:
Quoted 59 lines · Martin Schwidefsky
Quoted 49 lines · On Fri, 19 Aug 2011 09:48:36 -0400 Vivek Goyal <[email protected]> wrote:
Quoted 32 lines · Michael Holzheu

Hello Vivek,

Quoted 23 lines · Vivek Goyal
Quoted 15 lines · Michael Holzheu

From: Michael Holzheu <[email protected]>

On s390 we do not create page tables at all for the crashkernel memory. This requires a s390 specific version for kimage_load_crash_segment(). Therefore this patch declares this function as "__weak". The s390 version is very simple. It just copies the kexec segment to real memory without using page tables:

int kimage_load_crash_segment(struct kimage *image,
struct kexec_segment *segment)

{
        return copy_from_user_real((void *) segment->mem, segment->buf,
                                   segment->bufsz);
}
Quoted 6 lines

There are two main advantages of not creating page tables for the crashkernel memory:

a) It saves memory. We have scenarios in mind, where crashkernel memory can be very large and saving page table space is important.
b) We protect the crashkernel memory from being overwritten.

Quoted 5 lines

Michael,

Thinking more about it. Can't we provide a arch specific version of kmap() and kunmap() so that we create temporary mappings to copy the pages and then these are torn off.

Quoted 5 lines

Isn't kmap/kunmap() used for higmem? These functions are called from many different functions in the Linux kernel, not only for kdump. I would assume that creating and removing mappings with these functions is not what a caller would expect and probably would break the Linux kernel at many other places, no?

[CCing linux-mm]

Yes it is being used for highmem pages. If arch has not defined kmap() then generic definition is just returning page_address(page), expecting that page will be mapped.

I was wondering that what will be broken if arch decides to extend this to create temporary mappings for pages which are not HIGHMEM but do not have any mapping. (Like this special case of s390).

Quoted 6 lines

I guess memory management guys can give a better answer here. As a layman, kmap() seems to be the way to get a kernel mapping for any page frame and if one is not already there, then arch might create one on the fly, like we do for HIGHMEM pages. So the question is can be extend this to also cover pages which are not highmem but do not have any mappings on s390.

Quoted 6 lines

Imho it would be wrong to misuse kmap/kunmap to get around a minor problem with the memory for the crash kernel. These functions are used to provide accessibility to highmem pages in the kernel address space. The highmem area is "normal" memory with corresponding struct page elements (the functions do take a struct page * as argument after all). They are not usable to map arbitrary page frames.

Quoted 5 lines

Same is the case with crashkernel memory in s390 where these are normal pages, just that these are not mapped in linearly mapped region.

The only exception to highmem pages is that linearly mapped region is not big enough in certain arches, so we left them unmapped.

Well, the crashkernel memory in s390 is addressable without a page table but is not included in the mem_map array (no struct page). For the highmem page it is the other way round, the are not addressable without a page table entry but they are included in mem_map. That makes all the difference, no?

Quoted 11 lines
Quoted 3 lines

And we definitely don't want to make the memory management any slower by defining non-trivial kmap/kunmap functions.

if we continue to return page_address() and only go into else loop if page is not mapped, then there should not be any slow down for exisitng cases where memory is mapped?

Anyway, this was just a thought. I am not too particular about it and michael has agreed to get rid of code which was removing mappings for crashkernel area. So for the time we don't need above.

Then we can use the standard kimage_load_crash_segment function. But we should think about adding code that protects the crash kernel memory, e.g. by making the memory area read-only in the kernel page table. One reason why we wanted to exclude the crash kernel memory from the memory that is seen by the Linux kernel is protection from wild stores.

Signature · 4 lines
blue skies,
   Martin.

"Reality continues to ruin my life." - Calvin.
#10 lore raw

PATCH v3 3/8 kdump: Add size to elfcorehdr kernel parameter

In reply to Michael Holzheu

From: Michael Holzheu <[email protected]>

Currently only the address of the pre-allocated ELF header is passed with the elfcorehdr= kernel parameter. In order to reserve memory for the header in the 2nd kernel also the size is required. Current kdump architecture backends use different methods to do that, e.g. x86 uses the memmap= kernel parameter. On s390 there is no easy way to transfer this information. Therefore the elfcorehdr kernel parameter is extended to also pass the size. This now can also be used as standard mechanism by all future kdump architecture backends.

The syntax of the kernel parameter is extended as follows:

elfcorehdr=[size[KMG]@]offset[KMG]

This change is backward compatible because elfcorehdr=size is still allowed.

---
 Documentation/kernel-parameters.txt |    6 +++---
 include/linux/crash_dump.h          |    1 +
 kernel/crash_dump.c                 |   11 +++++++++++
 3 files changed, 15 insertions(+), 3 deletions(-)
Documentation/kernel-parameters.txt +3 -3
@@ -725,10 +725,10 @@ bytes respectively. Such letter suffixes
 			See Documentation/block/as-iosched.txt and
 			Documentation/block/deadline-iosched.txt for details.
 
-	elfcorehdr=	[IA64,PPC,SH,X86]
+	elfcorehdr=[size[KMG]@]offset[KMG] [IA64,PPC,SH,X86,S390]
 			Specifies physical address of start of kernel core
-			image elf header. Generally kexec loader will
-			pass this option to capture kernel.
+			image elf header and optionally the size. Generally
+			kexec loader will pass this option to capture kernel.
 			See Documentation/kdump/kdump.txt for details.
 
 	enable_mtrr_cleanup [X86]
include/linux/crash_dump.h +1 -0
@@ -10,6 +10,7 @@
 #define ELFCORE_ADDR_ERR	(-2ULL)
 
 extern unsigned long long elfcorehdr_addr;
+extern unsigned long long elfcorehdr_size;
 
 extern ssize_t copy_oldmem_page(unsigned long, char *, size_t,
 						unsigned long, int);
kernel/crash_dump.c +11 -0
@@ -20,8 +20,15 @@ unsigned long saved_max_pfn;
 unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
 
 /*
+ * stores the size of elf header of crash image
+ */
+unsigned long long elfcorehdr_size;
+
+/*
  * elfcorehdr= specifies the location of elf core header stored by the crashed
  * kernel. This option will be passed by kexec loader to the capture kernel.
+ *
+ * Syntax: elfcorehdr=[size[KMG]@]offset[KMG]
  */
 static int __init setup_elfcorehdr(char *arg)
 {
@@ -29,6 +36,10 @@ static int __init setup_elfcorehdr(char
 	if (!arg)
 		return -EINVAL;
 	elfcorehdr_addr = memparse(arg, &end);
+	if (*end == '@') {
+		elfcorehdr_size = elfcorehdr_addr;
+		elfcorehdr_addr = memparse(end + 1, &end);
+	}
 	return end > arg ? 0 : -EINVAL;
 }
 early_param("elfcorehdr", setup_elfcorehdr);
#11 lore raw

Re: [patch v3 3/8] kdump: Add size to elfcorehdr kernel parameter

Quoted 10 lines · Michael Holzheu

From: Michael Holzheu <[email protected]>

Currently only the address of the pre-allocated ELF header is passed with the elfcorehdr= kernel parameter. In order to reserve memory for the header in the 2nd kernel also the size is required. Current kdump architecture backends use different methods to do that, e.g. x86 uses the memmap= kernel parameter. On s390 there is no easy way to transfer this information. Therefore the elfcorehdr kernel parameter is extended to also pass the size. This now can also be used as standard mechanism by all future kdump architecture backends.

Michael,

This version looks much better. A quick question. Who parses this elfcorehdr= parameter in s390 and how do we make sure these headers are not overwritten.

Thanks
Vivek

#12 lore raw

Re: [patch v3 3/8] kdump: Add size to elfcorehdr kernel parameter

Hello Vivek,

Quoted 12 lines · Vivek Goyal
Quoted 10 lines · Michael Holzheu

From: Michael Holzheu <[email protected]>

Currently only the address of the pre-allocated ELF header is passed with the elfcorehdr= kernel parameter. In order to reserve memory for the header in the 2nd kernel also the size is required. Current kdump architecture backends use different methods to do that, e.g. x86 uses the memmap= kernel parameter. On s390 there is no easy way to transfer this information. Therefore the elfcorehdr kernel parameter is extended to also pass the size. This now can also be used as standard mechanism by all future kdump architecture backends.

Quoted 5 lines

Michael,

This version looks much better. A quick question. Who parses this elfcorehdr= parameter in s390 and how do we make sure these headers are not overwritten.

The parameter is parsed in common code (kernel/crash_dump.c) in early_param("elfcorehdr", setup_elfcorehdr), as it is already currently the case.

We use address and size of the ELF core header to reserve the header memory in setup.c (see patch #8):

+#ifdef CONFIG_CRASH_DUMP
+ if (is_kdump_kernel())
+ reserve_bootmem(elfcorehdr_addr - OLDMEM_BASE,
+ PAGE_ALIGN(elfcorehdr_size), BOOTMEM_DEFAULT);
+#endif

Does that answer your question?

Michael

#13 lore raw

Re: [patch v3 3/8] kdump: Add size to elfcorehdr kernel parameter

Quoted 34 lines · Michael Holzheu

Hello Vivek,

Quoted 12 lines · Vivek Goyal
Quoted 10 lines · Michael Holzheu

From: Michael Holzheu <[email protected]>

Currently only the address of the pre-allocated ELF header is passed with the elfcorehdr= kernel parameter. In order to reserve memory for the header in the 2nd kernel also the size is required. Current kdump architecture backends use different methods to do that, e.g. x86 uses the memmap= kernel parameter. On s390 there is no easy way to transfer this information. Therefore the elfcorehdr kernel parameter is extended to also pass the size. This now can also be used as standard mechanism by all future kdump architecture backends.

Quoted 5 lines

Michael,

This version looks much better. A quick question. Who parses this elfcorehdr= parameter in s390 and how do we make sure these headers are not overwritten.

The parameter is parsed in common code (kernel/crash_dump.c) in early_param("elfcorehdr", setup_elfcorehdr), as it is already currently the case.

We use address and size of the ELF core header to reserve the header memory in setup.c (see patch #8):

(quoted diff) +5 -0
+#ifdef CONFIG_CRASH_DUMP
+       if (is_kdump_kernel())
+               reserve_bootmem(elfcorehdr_addr - OLDMEM_BASE,
+                               PAGE_ALIGN(elfcorehdr_size), BOOTMEM_DEFAULT);
+#endif
Quoted 1 line

Does that answer your question?

Yes it does. Thanks.

It brings up few more questions about rest of the memory mangement.

So kdump kernel is loaded in reserved area but does not run from there. It reloads itself into lower memory areas and swaps the contents of lower memory with reserved memory? If yes, how does it, kernel or purgatory?

How does kernel come to know about how much memory is to be swapped and how do you bound the memory usage of second kernel so that it does not try to use other memory which has not been swapped into reserved area.

Thanks
Vivek

#14 lore raw

Re: [patch v3 3/8] kdump: Add size to elfcorehdr kernel parameter

Hello Vivek,

Quoted 17 lines · Vivek Goyal
Quoted 13 lines

The parameter is parsed in common code (kernel/crash_dump.c) in early_param("elfcorehdr", setup_elfcorehdr), as it is already currently the case.

We use address and size of the ELF core header to reserve the header memory in setup.c (see patch #8):

(quoted diff) +5 -0
+#ifdef CONFIG_CRASH_DUMP
+       if (is_kdump_kernel())
+               reserve_bootmem(elfcorehdr_addr - OLDMEM_BASE,
+                               PAGE_ALIGN(elfcorehdr_size), BOOTMEM_DEFAULT);
+#endif
Quoted 1 line

Does that answer your question?

Yes it does. Thanks.

Quoted 6 lines

It brings up few more questions about rest of the memory mangement.

So kdump kernel is loaded in reserved area but does not run from there. It reloads itself into lower memory areas and swaps the contents of lower memory with reserved memory? If yes, how does it, kernel or purgatory?

With the v3 patch series purgatory does that (see
purgatory-s390.c/post_verification_setup_arch()):

Quoted 1 line

How does kernel come to know about how much memory is to be swapped

2nd kernel knows crash_base and crash_base because kexec tools told him that. We do it like registering the ramdisk. See kexec-image.c:

+ if (info->kexec_flags & KEXEC_ON_CRASH) {
+ tmp = krnl_buffer + OLDMEM_BASE_OFFS;
+ *tmp = crash_base;
+
+ tmp = krnl_buffer + OLDMEM_SIZE_OFFS;
+ *tmp = crash_end - crash_base + 1;
+ }

Quoted 3 lines

and how do you bound the memory usage of second kernel so that it does not try to use other memory which has not been swapped into reserved area.

See kernel patches setup.c:

+/*
+ * Make sure that oldmem, where the dump is stored, is protected
+ */
+static void reserve_oldmem(void)
+{
+#ifdef CONFIG_CRASH_DUMP
+ if (!is_kdump_kernel())
+ return;
+
+ reserve_kdump_bootmem(OLDMEM_BASE, OLDMEM_SIZE, CHUNK_OLDMEM);
+ reserve_kdump_bootmem(OLDMEM_SIZE, memory_end - OLDMEM_SIZE,
+ CHUNK_OLDMEM);
+ if (OLDMEM_BASE + OLDMEM_SIZE == real_memory_size)
+ saved_max_pfn = PFN_DOWN(OLDMEM_BASE) - 1;
+ else
+ saved_max_pfn = PFN_DOWN(real_memory_size) - 1;
+#endif
+}

Michael

#15 lore raw

PATCH v3 4/8 s390: Add real memory access functions

In reply to Michael Holzheu

From: Michael Holzheu <[email protected]>

Add access function for real memory needed by s390 kdump backend.

---
 arch/s390/include/asm/system.h |    2 +
 arch/s390/mm/maccess.c         |   57 +++++++++++++++++++++++++++++++++++++++++
 drivers/s390/char/zcore.c      |   20 +-------------
 3 files changed, 61 insertions(+), 18 deletions(-)
arch/s390/include/asm/system.h +2 -0
@@ -114,6 +114,8 @@ extern void pfault_fini(void);
 extern void cmma_init(void);
 extern int memcpy_real(void *, void *, size_t);
 extern void copy_to_absolute_zero(void *dest, void *src, size_t count);
+extern int copy_to_user_real(void __user *dest, void *src, size_t count);
+extern int copy_from_user_real(void *dest, void __user *src, size_t count);
 
 #define finish_arch_switch(prev) do {					     \
 	set_fs(current->thread.mm_segment);				     \
arch/s390/mm/maccess.c +57 -0

72 lines not on this page · raw message

drivers/s390/char/zcore.c +2 -18
@@ -142,22 +142,6 @@ static int memcpy_hsa_kernel(void *dest,
 	return memcpy_hsa(dest, src, count, TO_KERNEL);
 }
 
-static int memcpy_real_user(void __user *dest, unsigned long src, size_t count)
-{
-	static char buf[4096];
-	int offs = 0, size;
-
-	while (offs < count) {
-		size = min(sizeof(buf), count - offs);
-		if (memcpy_real(buf, (void *) src + offs, size))
-			return -EFAULT;
-		if (copy_to_user(dest + offs, buf, size))
-			return -EFAULT;
-		offs += size;
-	}
-	return 0;
-}
-
 static int __init init_cpu_info(enum arch_id arch)
 {
 	struct save_area *sa;
@@ -346,8 +330,8 @@ static ssize_t zcore_read(struct file *f
 
 	/* Copy from real mem */
 	size = count - mem_offs - hdr_count;
-	rc = memcpy_real_user(buf + hdr_count + mem_offs, mem_start + mem_offs,
-			      size);
+	rc = copy_to_user_real(buf + hdr_count + mem_offs,
+			       (void *) mem_start + mem_offs, size);
 	if (rc)
 		goto fail;
 
#16 lore raw

PATCH v3 5/8 s390: kdump backend code

In reply to Michael Holzheu

From: Michael Holzheu <[email protected]>

This patch provides the architecture specific part of the s390 kdump support.

---
 arch/s390/Kconfig                |   10 +
 arch/s390/include/asm/ipl.h      |    1 
 arch/s390/include/asm/kexec.h    |    3 
 arch/s390/include/asm/setup.h    |    9 +
 arch/s390/kernel/Makefile        |    1 
 arch/s390/kernel/crash_dump.c    |   39 +++++
 arch/s390/kernel/head.S          |   16 ++
 arch/s390/kernel/head_kdump.S    |  116 +++++++++++++++++
 arch/s390/kernel/ipl.c           |    4 
 arch/s390/kernel/machine_kexec.c |  255 +++++++++++++++++++++++++++++++++++++++
 arch/s390/kernel/mem_detect.c    |   69 ++++++++++
 arch/s390/kernel/setup.c         |  190 +++++++++++++++++++++++++++++
 arch/s390/mm/vmem.c              |    3 
 13 files changed, 716 insertions(+)
arch/s390/Kconfig +10 -0
@@ -568,6 +568,16 @@ config KEXEC
 	  current kernel, and to start another kernel.  It is like a reboot
 	  but is independent of hardware/microcode support.
 
+config CRASH_DUMP
+	bool "kernel crash dumps"
+	depends on 64BIT
+	help
+	  Generate crash dump after being started by kexec.
+	  Crash dump kernels are loaded in the main kernel with kexec-tools
+	  into a specially reserved region and then later executed after
+	  a crash by kdump/kexec.
+	  For more details see Documentation/kdump/kdump.txt
+
 config ZFCPDUMP
 	def_bool n
 	prompt "zfcpdump support"
arch/s390/include/asm/ipl.h +1 -0
@@ -168,5 +168,6 @@ enum diag308_rc {
 
 extern int diag308(unsigned long subcode, void *addr);
 extern void diag308_reset(void);
+extern void store_status(void);
 
 #endif /* _ASM_S390_IPL_H */
arch/s390/include/asm/kexec.h +3 -0
@@ -30,6 +30,9 @@
 /* Not more than 2GB */
 #define KEXEC_CONTROL_MEMORY_LIMIT (1UL<<31)
 
+/* Maximum address we can use for the crash control pages */
+#define KEXEC_CRASH_CONTROL_MEMORY_LIMIT (-1UL)
+
 /* Allocate one page for the pdp and the second for the code */
 #define KEXEC_CONTROL_PAGE_SIZE 4096
 
arch/s390/include/asm/setup.h +9 -0
@@ -30,11 +30,15 @@
 #define IPL_DEVICE        (*(unsigned long *)  (0x10400))
 #define INITRD_START      (*(unsigned long *)  (0x10408))
 #define INITRD_SIZE       (*(unsigned long *)  (0x10410))
+#define OLDMEM_BASE       (*(unsigned long *)  (0x10418))
+#define OLDMEM_SIZE       (*(unsigned long *)  (0x10420))
 #endif /* __s390x__ */
 #define COMMAND_LINE      ((char *)            (0x10480))
 
 #define CHUNK_READ_WRITE 0
 #define CHUNK_READ_ONLY  1
+#define CHUNK_OLDMEM     4
+#define CHUNK_CRASHK     5
 
 struct mem_chunk {
 	unsigned long addr;
@@ -48,6 +52,8 @@ extern int memory_end_set;
 extern unsigned long memory_end;
 
 void detect_memory_layout(struct mem_chunk chunk[]);
+void create_mem_hole(struct mem_chunk memory_chunk[], unsigned long addr,
+		     unsigned long size, int type);
 
 #define PRIMARY_SPACE_MODE	0
 #define ACCESS_REGISTER_MODE	1
@@ -106,6 +112,7 @@ extern unsigned int user_mode;
 #endif /* __s390x__ */
 
 #define ZFCPDUMP_HSA_SIZE	(32UL<<20)
+#define ZFCPDUMP_HSA_SIZE_MAX	(64UL<<20)
 
 /*
  * Console mode. Override with conmode=
@@ -138,6 +145,8 @@ extern char kernel_nss_name[];
 #define IPL_DEVICE        0x10400
 #define INITRD_START      0x10408
 #define INITRD_SIZE       0x10410
+#define OLDMEM_BASE       0x10418
+#define OLDMEM_SIZE       0x10420
 #endif /* __s390x__ */
 #define COMMAND_LINE      0x10480
 
arch/s390/kernel/Makefile +1 -0
@@ -48,6 +48,7 @@ obj-$(CONFIG_FUNCTION_TRACER)	+= $(if $(
 obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o
 obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
 obj-$(CONFIG_FTRACE_SYSCALLS)  += ftrace.o
+obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
 
 # Kexec part
 S390_KEXEC_OBJS := machine_kexec.o crash.o
arch/s390/kernel/crash_dump.c new file +39 -0
@@ -0,0 +1,39 @@
+/*
+ * S390 kdump implementation
+ *
+ * Copyright IBM Corp. 2011
+ * Author(s): Michael Holzheu <[email protected]>
+ */
+
+#include <linux/crash_dump.h>
+#include <asm/lowcore.h>
+
+/*
+ * Copy one page from "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)
+{
+	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 &&
+		 src < OLDMEM_BASE + OLDMEM_SIZE)
+		src -= OLDMEM_BASE;
+	if (userbuf)
+		rc = copy_to_user_real((void __user *) buf, (void *) src,
+				       csize);
+	else
+		rc = memcpy_real(buf, (void *) src, csize);
+	return rc < 0 ? rc : csize;
+}
arch/s390/kernel/head.S +16 -0
@@ -449,10 +449,22 @@ ENTRY(start)
 #
 	.org	0x10000
 ENTRY(startup)
+	j	.Lep_startup_normal
+	.org	0x10008
+	.ascii	"S390EP"
+	.byte	0x00,0x01
+#
+# kdump startup-code at 0x10010, running in 64 bit absolute addressing mode
+#
+	.org	0x10010
+ENTRY(startup_kdump)
+	j	.Lep_startup_kdump
+.Lep_startup_normal:
 	basr	%r13,0			# get base
 .LPG0:
 	xc	0x200(256),0x200	# partially clear lowcore
 	xc	0x300(256),0x300
+	xc	0xe00(256),0xe00
 	stck	__LC_LAST_UPDATE_CLOCK
 	spt	5f-.LPG0(%r13)
 	mvc	__LC_LAST_UPDATE_TIMER(8),5f-.LPG0(%r13)
@@ -534,6 +546,8 @@ ENTRY(startup)
 	.align	8
 5:	.long	0x7fffffff,0xffffffff
 
+#include "head_kdump.S"
+
 #
 # params at 10400 (setup.h)
 #
@@ -541,6 +555,8 @@ ENTRY(startup)
 	.long	0,0			# IPL_DEVICE
 	.long	0,0			# INITRD_START
 	.long	0,0			# INITRD_SIZE
+	.long	0,0			# OLDMEM_BASE
+	.long	0,0			# OLDMEM_SIZE
 
 	.org	COMMAND_LINE
 	.byte	"root=/dev/ram0 ro"
arch/s390/kernel/head_kdump.S new file +116 -0

116 lines not on this page · raw message

arch/s390/kernel/ipl.c +4 -0
@@ -16,6 +16,7 @@
 #include <linux/ctype.h>
 #include <linux/fs.h>
 #include <linux/gfp.h>
+#include <linux/crash_dump.h>
 #include <asm/ipl.h>
 #include <asm/smp.h>
 #include <asm/setup.h>
@@ -1738,6 +1739,9 @@ static struct kobj_attribute on_restart_
 void do_restart(void)
 {
 	smp_send_stop();
+#ifdef CONFIG_CRASH_DUMP
+	crash_kexec(NULL);
+#endif
 	on_restart_trigger.action->fn(&on_restart_trigger);
 	stop_run(&on_restart_trigger);
 }
arch/s390/kernel/machine_kexec.c +255 -0

279 lines not on this page · raw message

arch/s390/kernel/mem_detect.c +69 -0

72 lines not on this page · raw message

arch/s390/kernel/setup.c +190 -0

238 lines not on this page · raw message

arch/s390/mm/vmem.c +3 -0
@@ -335,6 +335,9 @@ void __init vmem_map_init(void)
 	ro_start = ((unsigned long)&_stext) & PAGE_MASK;
 	ro_end = PFN_ALIGN((unsigned long)&_eshared);
 	for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
+		if (memory_chunk[i].type == CHUNK_CRASHK ||
+		    memory_chunk[i].type == CHUNK_OLDMEM)
+			continue;
 		start = memory_chunk[i].addr;
 		end = memory_chunk[i].addr + memory_chunk[i].size;
 		if (start >= ro_end || end <= ro_start)
#17 lore raw

PATCH v3 6/8 s390: Do first kdump checksum test before really starting kdump

In reply to Michael Holzheu

From: Michael Holzheu <[email protected]>

With this patch first the kdump checksums in purgatory are verified (with start_kdump(0)) before kdump is started. This allows us to do the shutdown actions defined under /sys/firmware as recovery action in case kdump is overwritten. The main use case is to define stand-alone dump as recovery action.

We have to split the purgatory function into "checksum test" and "real execution", because we have to switch to the IPL CPU when we execute kdump. After the switch it is not possible to return from the called function.

---
 arch/s390/kernel/machine_kexec.c |   10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)
arch/s390/kernel/machine_kexec.c +9 -1
@@ -325,8 +325,16 @@ void machine_kexec(struct kimage *image)
 {
 	tracer_disable();
 #ifdef CONFIG_CRASH_DUMP
-	if (image->type == KEXEC_TYPE_CRASH)
+	if (image->type == KEXEC_TYPE_CRASH) {
+		int (*start_kdump)(int) = (void *)image->start;
+		int rc;
+		__arch_local_irq_stnsm(0xfb); /* disable DAT */
+		rc = start_kdump(0);
+		__arch_local_irq_stosm(0x04); /* enable DAT */
+		if (rc)
+			return;
 		smp_switch_to_ipl_cpu(__machine_kdump, image);
+	}
 #endif
 	smp_send_stop();
 	smp_switch_to_ipl_cpu(__machine_kexec, image);
#18 lore raw

PATCH v3 7/8 kexec-tools: Add s390 kdump support

In reply to Michael Holzheu

From: Michael Holzheu <[email protected]>

This patch adds kdump support for s390 to the kexec tool and enables the "--load-panic" option. When loading the kdump kernel and ramdisk we add the address of the crashkernel memory to the normal load address.

---
 include/elf.h                        |    8 ++-
 kexec/arch/s390/Makefile             |    1 
 kexec/arch/s390/crashdump-s390.c     |   62 +++++++++++++++++++++++
 kexec/arch/s390/kexec-elf-rel-s390.c |   66 +++++++++++++++++++++---
 kexec/arch/s390/kexec-image.c        |   69 ++++++++++++++++++-------
 kexec/arch/s390/kexec-s390.c         |   66 +++++++++++++++++-------
 kexec/arch/s390/kexec-s390.h         |    9 +++
 purgatory/arch/s390/Makefile         |    4 +
 purgatory/arch/s390/console-s390.c   |   14 +++++
 purgatory/arch/s390/purgatory-s390.c |   93 +++++++++++++++++++++++++++++++++++
 purgatory/arch/s390/setup-s390.S     |   33 ++++++++++++
 11 files changed, 376 insertions(+), 49 deletions(-)
include/elf.h +6 -2
@@ -2304,9 +2304,13 @@ typedef Elf32_Addr Elf32_Conflict;
 #define R_390_TLS_DTPOFF	55	/* Offset in TLS block.	 */
 #define R_390_TLS_TPOFF		56	/* Negated offset in static TLS
 					   block.  */
-
+#define R_390_20		57	/* Direct 20 bit.  */
+#define R_390_GOT20		58	/* 20 bit GOT offset.  */
+#define R_390_GOTPLT20		59	/* 20 bit offset to jump slot.  */
+#define R_390_TLS_GOTIE20	60	/* 20 bit GOT offset for static TLS
+					   block offset.  */
 /* Keep this the last entry.  */
-#define R_390_NUM		57
+#define R_390_NUM		61
 
 /* CRIS relocations.  */
 #define R_CRIS_NONE		0
kexec/arch/s390/Makefile +1 -0
@@ -4,6 +4,7 @@
 s390_KEXEC_SRCS =  kexec/arch/s390/kexec-s390.c
 s390_KEXEC_SRCS += kexec/arch/s390/kexec-image.c
 s390_KEXEC_SRCS += kexec/arch/s390/kexec-elf-rel-s390.c
+s390_KEXEC_SRCS += kexec/arch/s390/crashdump-s390.c
 
 dist += kexec/arch/s390/Makefile $(s390_KEXEC_SRCS)			\
 	kexec/arch/s390/kexec-s390.h					\
kexec/arch/s390/crashdump-s390.c new file +62 -0

62 lines not on this page · raw message

kexec/arch/s390/kexec-elf-rel-s390.c +58 -8

80 lines not on this page · raw message

kexec/arch/s390/kexec-image.c +50 -19

128 lines not on this page · raw message

kexec/arch/s390/kexec-s390.c +47 -19

103 lines not on this page · raw message

kexec/arch/s390/kexec-s390.h +9 -0
@@ -15,11 +15,20 @@
 #define RAMDISK_ORIGIN_ADDR   0x800000
 #define INITRD_START_OFFS     0x408
 #define INITRD_SIZE_OFFS      0x410
+#define OLDMEM_BASE_OFFS      0x418
+#define OLDMEM_SIZE_OFFS      0x420
 #define COMMAND_LINE_OFFS     0x480
 #define COMMAND_LINESIZE      896
+#define MAX_MEMORY_RANGES     64
 
 extern int image_s390_load(int, char **, const char *, off_t, struct kexec_info *);
 extern int image_s390_probe(const char *, off_t);
 extern void image_s390_usage(void);
+extern int load_crashdump_segments(struct kexec_info *info,
+				   unsigned long crash_base,
+				   unsigned long crash_end);
+extern int get_memory_ranges_s390(struct memory_range range[], int *ranges,
+				  int with_crashk);
+extern int command_line_add(const char *str);
 
 #endif /* KEXEC_IA64_H */
purgatory/arch/s390/Makefile +3 -1
@@ -2,7 +2,9 @@
 # Purgatory s390
 #
 
-s390_PURGATORY_SRCS =
+s390_PURGATORY_SRCS += purgatory/arch/s390/console-s390.c
+s390_PURGATORY_SRCS += purgatory/arch/s390/setup-s390.S
+s390_PURGATORY_SRCS += purgatory/arch/s390/purgatory-s390.c
 
 dist += purgatory/arch/s390/Makefile $(s390_PURGATORY_SRCS)
 
purgatory/arch/s390/console-s390.c new file +14 -0
@@ -0,0 +1,14 @@
+/*
+ * S390 console code (currently not implemented)
+ *
+ * Copyright IBM Corp. 2011
+ *
+ * Author(s): Michael Holzheu <[email protected]>
+ */
+
+#include <purgatory.h>
+#include "unused.h"
+
+void putchar(int UNUSED(ch))
+{
+}
purgatory/arch/s390/purgatory-s390.c new file +93 -0

93 lines not on this page · raw message

purgatory/arch/s390/setup-s390.S new file +33 -0
@@ -0,0 +1,33 @@
+/*
+ * Purgatory setup code
+ *
+ * Copyright IBM Corp. 2011
+ *
+ * Author(s): Michael Holzheu <[email protected]>
+ */
+
+	.text
+	.globl purgatory_start
+	.balign 16
+purgatory_start:
+#ifdef __s390x__
+	larl	%r15,lstack_end
+	aghi	%r15,-160
+	brasl	%r14,purgatory
+	larl	%r14,kdump_psw
+	lpswe	0(%r14)
+
+	.section ".data"
+	.balign 16
+kdump_psw:
+	.quad 0x0000000180000000
+	.quad 0x0000000000010010
+
+	.bss
+	.balign 4096
+lstack:
+	.skip 4096
+lstack_end:
+#else
+0:	j	0
+#endif
#19 lore raw

PATCH v3 8/8 kexec-tools: Allow to call verify_sha256_digest() from kernel

In reply to Michael Holzheu

From: Michael Holzheu <[email protected]>

For s390 we first want to check if kdump checksums are valid before we start the kdump kernel. With this patch on s390 the purgatory entry point is called with a parameter. If the parameter is "0", only the checksum test is done and the result (0 = ok, 1 = invalid) is passed as return code back to the caller (kernel). If the parameter is "1", the complete purgatory code is executed and kdump is started.

---
 purgatory/arch/s390/setup-s390.S |   14 ++++++++++++++
 purgatory/purgatory.c            |   13 ++++++++-----
 2 files changed, 22 insertions(+), 5 deletions(-)
purgatory/arch/s390/setup-s390.S +14 -0
@@ -11,12 +11,23 @@
 	.balign 16
 purgatory_start:
 #ifdef __s390x__
+	larl	%r5,gprs_save_area
+	stmg	%r6,%r15,0(%r5)
 	larl	%r15,lstack_end
 	aghi	%r15,-160
+
+	clgfi	%r2,0
+	je	verify_checksums
+
 	brasl	%r14,purgatory
 	larl	%r14,kdump_psw
 	lpswe	0(%r14)
 
+verify_checksums:
+	brasl	%r14,verify_sha256_digest
+	larl	%r5,gprs_save_area
+	lmg	%r6,%r15,0(%r5)
+	br	%r14
 	.section ".data"
 	.balign 16
 kdump_psw:
@@ -24,6 +35,9 @@ kdump_psw:
 	.quad 0x0000000000010010
 
 	.bss
+gprs_save_area:
+	.fill 80
+
 	.balign 4096
 lstack:
 	.skip 4096
purgatory/purgatory.c +8 -5
@@ -9,7 +9,7 @@
 struct sha256_region sha256_regions[SHA256_REGIONS] = {};
 sha256_digest_t sha256_digest = { };
 
-void verify_sha256_digest(void)
+int verify_sha256_digest(void)
 {
 	struct sha256_region *ptr, *end;
 	sha256_digest_t digest;
@@ -34,16 +34,19 @@ void verify_sha256_digest(void)
 			printf("%hhx ", sha256_digest[i]);
 		}
 		printf("\n");
-		for(;;) {
-			/* loop forever */
-		}
+		return 1;
 	}
+	return 0;
 }
 
 void purgatory(void)
 {
 	printf("I'm in purgatory\n");
 	setup_arch();
-	verify_sha256_digest();
+	if (verify_sha256_digest()) {
+		for(;;) {
+			/* loop forever */
+		}
+	}
 	post_verification_setup_arch();
 }