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, &notes_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
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to