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. Also, setup opal base & entry values in r8 & r9
registers to help early OPAL debugging.

Signed-off-by: Hari Bathini <hbath...@linux.ibm.com>
Tested-by: Pingfan Liu <pi...@redhat.com>
Reviewed-by: Thiago Jung Bauermann <bauer...@linux.ibm.com>
---

v3 -> v4:
* Fixed stack_buf to be quadword aligned in accordance with ABI.
* Added missing of_node_put() in setup_purgatory_ppc64().
* Added Reviewed-by tag from Thiago.

v2 -> v3:
* Unchanged. Added Tested-by tag from Pingfan.

v1 -> v2:
* Setting up opal base & entry values in r8 & r9 for early OPAL debug.


 arch/powerpc/include/asm/kexec.h       |    4 ++++
 arch/powerpc/kexec/file_load_64.c      |   30 ++++++++++++++++++++++++++++++
 arch/powerpc/purgatory/trampoline_64.S |   32 ++++++++++++++++++++++++++++++++
 3 files changed, 66 insertions(+)

diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h
index 835dc92..00988da 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 20e638d..7f1f31c 100644
--- a/arch/powerpc/kexec/file_load_64.c
+++ b/arch/powerpc/kexec/file_load_64.c
@@ -946,6 +946,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)
 {
+       struct device_node *dn = NULL;
+       void *stack_buf;
        uint64_t val;
        int ret;
 
@@ -969,13 +971,41 @@ 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;
+
+       val = (u64)stack_buf + KEXEC_PURGATORY_STACK_SIZE;
+       ret = kexec_purgatory_get_set_symbol(image, "stack", &val, sizeof(val),
+                                            false);
+       if (ret)
+               goto out;
+
        /* Setup the TOC pointer */
        val = get_toc_ptr(&(image->purgatory_info));
        ret = kexec_purgatory_get_set_symbol(image, "my_toc", &val, sizeof(val),
                                             false);
+       if (ret)
+               goto out;
+
+       /* Setup OPAL base & entry values */
+       dn = of_find_node_by_path("/ibm,opal");
+       if (dn) {
+               of_property_read_u64(dn, "opal-base-address", &val);
+               ret = kexec_purgatory_get_set_symbol(image, "opal_base", &val,
+                                                    sizeof(val), false);
+               if (ret)
+                       goto out;
+
+               of_property_read_u64(dn, "opal-entry-address", &val);
+               ret = kexec_purgatory_get_set_symbol(image, "opal_entry", &val,
+                                                    sizeof(val), false);
+       }
 out:
        if (ret)
                pr_err("Failed to setup purgatory symbols");
+       of_node_put(dn);
        return ret;
 }
 
diff --git a/arch/powerpc/purgatory/trampoline_64.S 
b/arch/powerpc/purgatory/trampoline_64.S
index b375843..1615dfc 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 */
@@ -63,6 +66,10 @@ master:
        li      %r4,28
        STWX_BE %r17,%r3,%r4    /* Store my cpu as __be32 at byte 28 */
 1:
+       /* Load opal base and entry values in r8 & r9 respectively */
+       ld      %r8,(opal_base - 0b)(%r18)
+       ld      %r9,(opal_entry - 0b)(%r18)
+
        /* load the kernel address */
        ld      %r4,(kernel - 0b)(%r18)
 
@@ -110,6 +117,24 @@ my_toc:
        .8byte  0x0
        .size my_toc, . - my_toc
 
+       .balign 8
+       .globl stack
+stack:
+       .8byte  0x0
+       .size stack, . - stack
+
+       .balign 8
+       .globl opal_base
+opal_base:
+       .8byte  0x0
+       .size opal_base, . - opal_base
+
+       .balign 8
+       .globl opal_entry
+opal_entry:
+       .8byte  0x0
+       .size opal_entry, . - opal_entry
+
        .data
        .balign 8
 .globl purgatory_sha256_digest
@@ -122,3 +147,10 @@ purgatory_sha256_digest:
 purgatory_sha_regions:
        .skip   8 * 2 * 16
        .size purgatory_sha_regions, . - purgatory_sha_regions
+
+       /* Stack must be quadword aligned */
+       .balign 16
+.globl stack_buf
+stack_buf:
+       .skip   KEXEC_PURGATORY_STACK_SIZE
+       .size stack_buf, . - stack_buf

Reply via email to