To avoid any weird errors, the purgatory should run with its own
stack. Set one up by adding the stack buffer to .data section of
the purgatory.

Signed-off-by: Hari Bathini <hbath...@linux.ibm.com>
---
 arch/powerpc/include/asm/kexec.h       |    4 ++++
 arch/powerpc/kexec/file_load_64.c      |   14 +++++++++++++-
 arch/powerpc/purgatory/trampoline_64.S |   15 +++++++++++++++
 3 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h
index bf47a01..e78cd0a 100644
--- a/arch/powerpc/include/asm/kexec.h
+++ b/arch/powerpc/include/asm/kexec.h
@@ -45,6 +45,10 @@
 #define KEXEC_ARCH KEXEC_ARCH_PPC
 #endif
 
+#ifdef CONFIG_KEXEC_FILE
+#define KEXEC_PURGATORY_STACK_SIZE     16384   /* 16KB stack size */
+#endif
+
 #define KEXEC_STATE_NONE 0
 #define KEXEC_STATE_IRQS_OFF 1
 #define KEXEC_STATE_REAL_MODE 2
diff --git a/arch/powerpc/kexec/file_load_64.c 
b/arch/powerpc/kexec/file_load_64.c
index 4430336..8e66c28 100644
--- a/arch/powerpc/kexec/file_load_64.c
+++ b/arch/powerpc/kexec/file_load_64.c
@@ -878,7 +878,8 @@ int setup_purgatory_ppc64(struct kimage *image, const void 
*slave_code,
                          const void *fdt, unsigned long kernel_load_addr,
                          unsigned long fdt_load_addr)
 {
-       uint64_t toc_ptr;
+       uint64_t toc_ptr, stack_top;
+       void *stack_buf;
        int ret;
 
        ret = setup_purgatory(image, slave_code, fdt, kernel_load_addr,
@@ -901,6 +902,17 @@ int setup_purgatory_ppc64(struct kimage *image, const void 
*slave_code,
                        goto out;
        }
 
+       /* Setup the stack top */
+       stack_buf = kexec_purgatory_get_symbol_addr(image, "stack_buf");
+       if (!stack_buf)
+               goto out;
+
+       stack_top = (u64)stack_buf + KEXEC_PURGATORY_STACK_SIZE;
+       ret = kexec_purgatory_get_set_symbol(image, "stack", &stack_top,
+                                            sizeof(stack_top), false);
+       if (ret)
+               goto out;
+
        /* Setup the TOC pointer */
        toc_ptr = get_toc_ptr(image->purgatory_info.ehdr);
        ret = kexec_purgatory_get_set_symbol(image, "my_toc", &toc_ptr,
diff --git a/arch/powerpc/purgatory/trampoline_64.S 
b/arch/powerpc/purgatory/trampoline_64.S
index 7b4a5f7..80615b4 100644
--- a/arch/powerpc/purgatory/trampoline_64.S
+++ b/arch/powerpc/purgatory/trampoline_64.S
@@ -9,6 +9,7 @@
  * Copyright (C) 2013, Anton Blanchard, IBM Corporation
  */
 
+#include <asm/kexec.h>
 #include <asm/asm-compat.h>
 
        .machine ppc64
@@ -53,6 +54,8 @@ master:
 
        ld      %r2,(my_toc - 0b)(%r18)         /* setup toc */
 
+       ld      %r1,(stack - 0b)(%r18)          /* setup stack */
+
        /* load device-tree address */
        ld      %r3, (dt_offset - 0b)(%r18)
        mr      %r16,%r3        /* save dt address in reg16 */
@@ -111,6 +114,12 @@ my_toc:
        .8byte  0x0
        .size my_toc, . - my_toc
 
+       .balign 8
+       .globl stack
+stack:
+       .8byte  0x0
+       .size stack, . - stack
+
        .data
        .balign 8
 .globl purgatory_sha256_digest
@@ -123,3 +132,9 @@ purgatory_sha256_digest:
 purgatory_sha_regions:
        .skip   8 * 2 * 16
        .size purgatory_sha_regions, . - purgatory_sha_regions
+
+       .balign 8
+.globl stack_buf
+stack_buf:
+       .skip   KEXEC_PURGATORY_STACK_SIZE
+       .size stack_buf, . - stack_buf

Reply via email to