Hi Dave, This patch is an attempt to get the ball rolling on SMP support for ARM. Regards, Per diff --git a/arm.c b/arm.c index 06b2f1c..bf346df 100644 --- a/arm.c +++ b/arm.c @@ -73,7 +73,7 @@ struct arm_cpu_context_save { /* * Holds registers during the crash. */ -static struct arm_pt_regs panic_task_regs; +static struct arm_pt_regs *panic_task_regs; #define PGDIR_SIZE() (4 * PAGESIZE()) #define PGDIR_OFFSET(X) (((ulong)(X)) & (PGDIR_SIZE() - 1)) @@ -484,71 +484,103 @@ arm_get_crash_notes(void) Elf32_Nhdr *note; ulong ptr, offset; char *buf, *p; + ulong *notes_ptrs; + ulong per_cpu_offsets_addr; + ulong *per_cpu_offsets; + ulong i; if (!symbol_exists("crash_notes")) return FALSE; crash_notes = symbol_value("crash_notes"); - if (kt->cpus > 1) - error(WARNING, "only one CPU is currently supported\n"); + notes_ptrs = GETBUF(kt->cpus*sizeof(notes_ptrs[0])); /* * Read crash_notes for the first CPU. crash_notes are in standard ELF * note format. */ - if (!readmem(crash_notes, KVADDR, &ptr, sizeof(ptr), "crash_notes", + if (!readmem(crash_notes, KVADDR, ¬es_ptrs[kt->cpus-1], sizeof(notes_ptrs[kt->cpus-1]), "crash_notes", RETURN_ON_ERROR)) { - error(WARNING, "cannot read crash_notes\n"); + error(WARNING, "cannot read crash_notes\n"); + return FALSE; + } + + + if (symbol_exists("__per_cpu_offset")) { + + /* Get the __per_cpu_offset array */ + per_cpu_offsets_addr = symbol_value("__per_cpu_offset"); + + per_cpu_offsets = GETBUF(kt->cpus*sizeof(*per_cpu_offsets)); + + if (!readmem(per_cpu_offsets_addr, KVADDR, per_cpu_offsets, kt->cpus*sizeof(*per_cpu_offsets), "per_cpu_offsets", + RETURN_ON_ERROR)) { + error(WARNING, "cannot read per_cpu_offsets\n"); return FALSE; + } + + /* Add __per_cpu_offset for each cpu to form the pointer to the notes */ + for (i = 0; i<kt->cpus; i++) { + notes_ptrs[i] = notes_ptrs[kt->cpus-1] + per_cpu_offsets[i]; + } + FREEBUF(per_cpu_offsets); } buf = GETBUF(SIZE(note_buf)); + panic_task_regs = GETBUF(kt->cpus*sizeof(*panic_task_regs)); + + for (i=0;i<kt->cpus;i++) { - if (!readmem(ptr, KVADDR, buf, SIZE(note_buf), "note_buf_t", - RETURN_ON_ERROR)) { + if (!readmem(notes_ptrs[i], KVADDR, buf, SIZE(note_buf), "note_buf_t", + RETURN_ON_ERROR)) { error(WARNING, "failed to read note_buf_t\n"); goto fail; - } + } - /* - * Do some sanity checks for this note before reading registers from it. - */ - note = (Elf32_Nhdr *)buf; - p = buf + sizeof(Elf32_Nhdr); + /* + * Do some sanity checks for this note before reading registers from it. + */ + note = (Elf32_Nhdr *)buf; + p = buf + sizeof(Elf32_Nhdr); - if (note->n_type != NT_PRSTATUS) { + if (note->n_type != NT_PRSTATUS) { error(WARNING, "invalid note (n_type != NT_PRSTATUS)\n"); goto fail; - } - if (p[0] != 'C' || p[1] != 'O' || p[2] != 'R' || p[3] != 'E') { + } + if (p[0] != 'C' || p[1] != 'O' || p[2] != 'R' || p[3] != 'E') { error(WARNING, "invalid note (name != \"CORE\"\n"); goto fail; - } + } - /* - * Find correct location of note data. This contains elf_prstatus - * structure which has registers etc. for the crashed task. - */ - offset = sizeof(Elf32_Nhdr); - offset = roundup(offset + note->n_namesz, 4); - p = buf + offset; /* start of elf_prstatus */ + /* + * Find correct location of note data. This contains elf_prstatus + * structure which has registers etc. for the crashed task. + */ + offset = sizeof(Elf32_Nhdr); + offset = roundup(offset + note->n_namesz, 4); + p = buf + offset; /* start of elf_prstatus */ - BCOPY(p + OFFSET(elf_prstatus_pr_reg), &panic_task_regs, - sizeof(panic_task_regs)); + BCOPY(p + OFFSET(elf_prstatus_pr_reg), &panic_task_regs[i], + sizeof(panic_task_regs[i])); + + } /* * And finally we have pid and registers for the crashed task. This is * used later on when dumping backtrace. */ ms->crash_task_pid = *(ulong *)(p + OFFSET(elf_prstatus_pr_pid)); - ms->crash_task_regs = &panic_task_regs; + ms->crash_task_regs = panic_task_regs; FREEBUF(buf); + FREEBUF(notes_ptrs); return TRUE; fail: FREEBUF(buf); + FREEBUF(notes_ptrs); + FREEBUF(panic_task_regs); return FALSE; } @@ -996,20 +1028,20 @@ arm_get_dumpfile_stack_frame(struct bt_info *bt, ulong *nip, ulong *ksp) if (!ms->crash_task_regs) return FALSE; - if (tt->panic_task != bt->task || bt->tc->pid != ms->crash_task_pid) - return FALSE; - + if (!is_task_active(bt->task)) + return FALSE; + /* * We got registers for panic task from crash_notes. Just return them. */ - *nip = ms->crash_task_regs->ARM_pc; - *ksp = ms->crash_task_regs->ARM_sp; + *nip = ms->crash_task_regs[bt->tc->processor].ARM_pc; + *ksp = ms->crash_task_regs[bt->tc->processor].ARM_sp; /* * Also store pointer to all registers in case unwinding code needs * to access LR. */ - bt->machdep = ms->crash_task_regs; + bt->machdep = &(ms->crash_task_regs[bt->tc->processor]); return TRUE; } diff --git a/defs.h b/defs.h index d431d6e..8a2291a 100755 --- a/defs.h +++ b/defs.h @@ -85,7 +85,7 @@ #define NR_CPUS (64) #endif #ifdef ARM -#define NR_CPUS (1) +#define NR_CPUS (4) #endif #define BUFSIZE (1500) -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility