summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuzuki K. Poulose <suzuki@in.ibm.com>2011-07-12 15:20:40 +0530
committerSimon Horman <horms@verge.net.au>2011-07-13 11:39:58 +0900
commit13f6d71bdf9836b90ae4ec21209383f1a3c56b0f (patch)
tree21eb51a4571b379ca52942fd41e304afb367a681
parent9ec3fac7e8840fb31891ba49a626c5dd33e09e86 (diff)
downloadkexec-tools-13f6d71bdf9836b90ae4ec21209383f1a3c56b0f.tar.gz
kexec-tools: ppc32: Fixup ThreadPointer for purgatory code
PPC32 ELF ABI expects r2 to be loaded with Thread Pointer, which is 0x7000 bytes past the end of TCB. Though the purgatory is single threaded, it uses TCB scratch space in vsnprintf(). This patch allocates a 1024byte TCB and populates the TP with the address accordingly. Changes from V2: Avoid address overflow in TP allocation. Changes from V1: Fixed the addr calculation for uImage support. Signed-off-by: Suzuki K. Poulose <suzuki@in.ibm.com> Cc: Ryan S. Arnold <rsa@us.ibm.com> Signed-off-by: Simon Horman <horms@verge.net.au>
-rw-r--r--kexec/arch/ppc/kexec-elf-ppc.c19
-rw-r--r--kexec/arch/ppc/kexec-uImage-ppc.c17
-rw-r--r--purgatory/arch/ppc/purgatory-ppc.c2
-rw-r--r--purgatory/arch/ppc/v2wrap_32.S4
4 files changed, 41 insertions, 1 deletions
diff --git a/kexec/arch/ppc/kexec-elf-ppc.c b/kexec/arch/ppc/kexec-elf-ppc.c
index f4443b49..314eb1eb 100644
--- a/kexec/arch/ppc/kexec-elf-ppc.c
+++ b/kexec/arch/ppc/kexec-elf-ppc.c
@@ -414,6 +414,25 @@ int elf_ppc_load(int argc, char **argv, const char *buf, off_t len,
elf_rel_set_symbol(&info->rhdr, "stack", &addr, sizeof(addr));
#undef PUL_STACK_SIZE
+ /*
+ * Fixup ThreadPointer(r2) for purgatory.
+ * PPC32 ELF ABI expects :
+ * ThreadPointer (TP) = TCB + 0x7000
+ * We manually allocate a TCB space and set the TP
+ * accordingly.
+ */
+#define TCB_SIZE 1024
+#define TCB_TP_OFFSET 0x7000 /* PPC32 ELF ABI */
+
+ addr = locate_hole(info, TCB_SIZE, 0, 0,
+ ((unsigned long)elf_max_addr(&ehdr) - TCB_TP_OFFSET),
+ 1);
+ addr += TCB_SIZE + TCB_TP_OFFSET;
+ elf_rel_set_symbol(&info->rhdr, "my_thread_ptr", &addr, sizeof(addr));
+
+#undef TCB_SIZE
+#undef TCB_TP_OFFSET
+
addr = elf_rel_get_addr(&info->rhdr, "purgatory_start");
info->entry = (void *)addr;
#endif
diff --git a/kexec/arch/ppc/kexec-uImage-ppc.c b/kexec/arch/ppc/kexec-uImage-ppc.c
index 1d71374a..b5579f03 100644
--- a/kexec/arch/ppc/kexec-uImage-ppc.c
+++ b/kexec/arch/ppc/kexec-uImage-ppc.c
@@ -228,6 +228,23 @@ static int ppc_load_bare_bits(int argc, char **argv, const char *buf,
/* No allocation past here in order not to overwrite the stack */
#undef PUL_STACK_SIZE
+ /*
+ * Fixup ThreadPointer(r2) for purgatory.
+ * PPC32 ELF ABI expects :
+ * ThreadPointer (TP) = TCB + 0x7000
+ * We manually allocate a TCB space and set the TP
+ * accordingly.
+ */
+#define TCB_SIZE 1024
+#define TCB_TP_OFFSET 0x7000 /* PPC32 ELF ABI */
+ addr = locate_hole(info, TCB_SIZE, 0, 0,
+ ((unsigned long)-1 - TCB_TP_OFFSET),
+ 1);
+ addr += TCB_SIZE + TCB_TP_OFFSET;
+ elf_rel_set_symbol(&info->rhdr, "my_thread_ptr", &addr, sizeof(addr));
+#undef TCB_TP_OFFSET
+#undef TCB_SIZE
+
addr = elf_rel_get_addr(&info->rhdr, "purgatory_start");
info->entry = (void *)addr;
diff --git a/purgatory/arch/ppc/purgatory-ppc.c b/purgatory/arch/ppc/purgatory-ppc.c
index 349e7505..3e6b354a 100644
--- a/purgatory/arch/ppc/purgatory-ppc.c
+++ b/purgatory/arch/ppc/purgatory-ppc.c
@@ -26,7 +26,7 @@ unsigned int panic_kernel = 0;
unsigned long backup_start = 0;
unsigned long stack = 0;
unsigned long dt_offset = 0;
-unsigned long my_toc = 0;
+unsigned long my_thread_ptr = 0;
unsigned long kernel = 0;
void setup_arch(void)
diff --git a/purgatory/arch/ppc/v2wrap_32.S b/purgatory/arch/ppc/v2wrap_32.S
index 8442d162..8b60677d 100644
--- a/purgatory/arch/ppc/v2wrap_32.S
+++ b/purgatory/arch/ppc/v2wrap_32.S
@@ -56,6 +56,10 @@ master:
mr 17,3 # save cpu id to r17
mr 15,4 # save physical address in reg15
+ lis 6,my_thread_ptr@h
+ ori 6,6,my_thread_ptr@l
+ lwz 2,0(6) # setup ThreadPointer(TP)
+
lis 6,stack@h
ori 6,6,stack@l
lwz 1,0(6) #setup stack