This patch adds support for reading the register set on PPC32,
from the ELF note in a dump.
Signed-off-by: Suzuki K. Poulose <suzuki(a)in.ibm.com>
---
netdump.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 71 insertions(+), 0 deletions(-)
diff --git a/netdump.c b/netdump.c
index c0ee9ae..f7bf7d8 100644
--- a/netdump.c
+++ b/netdump.c
@@ -33,6 +33,7 @@ static size_t dump_Elf32_Nhdr(Elf32_Off offset, int);
static void dump_Elf64_Ehdr(Elf64_Ehdr *);
static void dump_Elf64_Phdr(Elf64_Phdr *, int);
static size_t dump_Elf64_Nhdr(Elf64_Off offset, int);
+static void get_netdump_regs_ppc(struct bt_info *, ulong *, ulong *);
static void get_netdump_regs_ppc64(struct bt_info *, ulong *, ulong *);
static void get_netdump_regs_arm(struct bt_info *, ulong *, ulong *);
static physaddr_t xen_kdump_p2m(physaddr_t);
@@ -2172,6 +2173,10 @@ get_netdump_regs(struct bt_info *bt, ulong *eip, ulong *esp)
machdep->get_stack_frame(bt, eip, esp);
break;
+ case EM_PPC:
+ return get_netdump_regs_ppc(bt, eip, esp);
+ break;
+
case EM_PPC64:
return get_netdump_regs_ppc64(bt, eip, esp);
break;
@@ -2551,6 +2556,40 @@ next_sysrq:
}
static void
+get_netdump_regs_ppc(struct bt_info *bt, ulong *eip, ulong *esp)
+{
+ Elf32_Nhdr *note;
+ size_t len;
+
+ if ((bt->task == tt->panic_task) ||
+ (is_task_active(bt->task) && nd->num_prstatus_notes > 1)) {
+ /*
+ * Registers are saved during the dump process for the
+ * panic task. Whereas in kdump, regs are captured for all
+ * CPUs if they responded to an IPI.
+ */
+ if (nd->num_prstatus_notes > 1) {
+ if (!nd->nt_prstatus_percpu[bt->tc->processor])
+ error(FATAL,
+ "cannot determine NT_PRSTATUS ELF note "
+ "for %s task: %lx\n",
+ (bt->task == tt->panic_task) ?
+ "panic" : "active", bt->task);
+ note = (Elf32_Nhdr *)
+ nd->nt_prstatus_percpu[bt->tc->processor];
+ } else
+ note = (Elf32_Nhdr *)nd->nt_prstatus;
+
+ len = sizeof(Elf32_Nhdr);
+ len = roundup(len + note->n_namesz, 4);
+ bt->machdep = (void *)((char *)note + len +
+ MEMBER_OFFSET("elf_prstatus", "pr_reg"));
+ }
+
+ machdep->get_stack_frame(bt, eip, esp);
+}
+
+static void
get_netdump_regs_ppc64(struct bt_info *bt, ulong *eip, ulong *esp)
{
Elf64_Nhdr *note;
@@ -2838,6 +2877,7 @@ xen_minor_version(void)
* Contributed by: Sharyathi Nagesh (sharyath(a)in.ibm.com)
*/
+static void *get_ppc_regs_from_elf_notes(struct task_context *);
static void *get_ppc64_regs_from_elf_notes(struct task_context *);
static void *get_x86_regs_from_elf_notes(struct task_context *);
static void *get_x86_64_regs_from_elf_notes(struct task_context *);
@@ -2876,6 +2916,7 @@ get_regs_from_elf_notes(struct task_context *tc)
switch (e_machine)
{
case EM_386:
+ case EM_PPC:
case EM_PPC64:
case EM_X86_64:
case EM_ARM:
@@ -2895,6 +2936,8 @@ get_regs_from_elf_notes(struct task_context *tc)
{
case EM_386:
return get_x86_regs_from_elf_notes(tc);
+ case EM_PPC:
+ return get_ppc_regs_from_elf_notes(tc);
case EM_PPC64:
return get_ppc64_regs_from_elf_notes(tc);
case EM_X86_64:
@@ -2964,6 +3007,34 @@ get_x86_64_regs_from_elf_notes(struct task_context *tc)
}
static void *
+get_ppc_regs_from_elf_notes(struct task_context *tc)
+{
+ Elf32_Nhdr *note;
+ size_t len;
+ void *pt_regs;
+ extern struct vmcore_data *nd;
+
+ pt_regs = NULL;
+
+ /*
+ * Registers are always saved during the dump process for the
+ * panic task. Kdump also captures registers for all CPUs if
+ * they responded to an IPI.
+ */
+ if (nd->num_prstatus_notes > 1) {
+ note = (Elf32_Nhdr *)nd->nt_prstatus_percpu[tc->processor];
+ } else
+ note = (Elf32_Nhdr *)nd->nt_prstatus;
+
+ len = sizeof(Elf32_Nhdr);
+ len = roundup(len + note->n_namesz, 4);
+ pt_regs = (void *)((char *)note + len +
+ MEMBER_OFFSET("elf_prstatus", "pr_reg"));
+
+ return pt_regs;
+}
+
+static void *
get_ppc64_regs_from_elf_notes(struct task_context *tc)
{
Elf64_Nhdr *note;