summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 f4443b4..314eb1e 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 1d71374..b5579f0 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 349e750..3e6b354 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 8442d16..8b60677 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