OSDN Git Service

MIPS: Fix ejtag handler on SMP
authorHeiher <r@hev.cc>
Mon, 11 Jun 2018 09:01:10 +0000 (17:01 +0800)
committerPaul Burton <paul.burton@mips.com>
Sun, 24 Jun 2018 16:27:27 +0000 (09:27 -0700)
On SMP systems, the shared ejtag debug buffer may be overwritten by
other cores, because every cores can generate ejtag exception at
same time.

Unfortunately, in that context, it's difficult to relax more registers
to access per cpu buffers. so use ll/sc to serialize the access.

[paul.burton@mips.com:
  This could in theory be backported at least as far back as the
  beginning of the git era, however in general it's exceedingly rare
  that anyone would hit this without further changes, so it doesn't seem
  worthwhile marking for backport.]

Signed-off-by: Heiher <r@hev.cc>
Patchwork: https://patchwork.linux-mips.org/patch/19507/
Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: jhogan@kernel.org
Cc: ralf@linux-mips.org
arch/mips/kernel/genex.S

index 37b9383..6c257b5 100644 (file)
@@ -354,16 +354,56 @@ NESTED(ejtag_debug_handler, PT_SIZE, sp)
        sll     k0, k0, 30      # Check for SDBBP.
        bgez    k0, ejtag_return
 
+#ifdef CONFIG_SMP
+1:     PTR_LA  k0, ejtag_debug_buffer_spinlock
+       ll      k0, 0(k0)
+       bnez    k0, 1b
+       PTR_LA  k0, ejtag_debug_buffer_spinlock
+       sc      k0, 0(k0)
+       beqz    k0, 1b
+# ifdef CONFIG_WEAK_REORDERING_BEYOND_LLSC
+       sync
+# endif
+
+       PTR_LA  k0, ejtag_debug_buffer
+       LONG_S  k1, 0(k0)
+
+       ASM_CPUID_MFC0 k1, ASM_SMP_CPUID_REG
+       PTR_SRL k1, SMP_CPUID_PTRSHIFT
+       PTR_SLL k1, LONGLOG
+       PTR_LA  k0, ejtag_debug_buffer_per_cpu
+       PTR_ADDU k0, k1
+
+       PTR_LA  k1, ejtag_debug_buffer
+       LONG_L  k1, 0(k1)
+       LONG_S  k1, 0(k0)
+
+       PTR_LA  k0, ejtag_debug_buffer_spinlock
+       sw      zero, 0(k0)
+#else
        PTR_LA  k0, ejtag_debug_buffer
        LONG_S  k1, 0(k0)
+#endif
+
        SAVE_ALL
        move    a0, sp
        jal     ejtag_exception_handler
        RESTORE_ALL
+
+#ifdef CONFIG_SMP
+       ASM_CPUID_MFC0 k1, ASM_SMP_CPUID_REG
+       PTR_SRL k1, SMP_CPUID_PTRSHIFT
+       PTR_SLL k1, LONGLOG
+       PTR_LA  k0, ejtag_debug_buffer_per_cpu
+       PTR_ADDU k0, k1
+       LONG_L  k1, 0(k0)
+#else
        PTR_LA  k0, ejtag_debug_buffer
        LONG_L  k1, 0(k0)
+#endif
 
 ejtag_return:
+       back_to_back_c0_hazard
        MFC0    k0, CP0_DESAVE
        .set    mips32
        deret
@@ -377,6 +417,12 @@ ejtag_return:
        .data
 EXPORT(ejtag_debug_buffer)
        .fill   LONGSIZE
+#ifdef CONFIG_SMP
+EXPORT(ejtag_debug_buffer_spinlock)
+       .fill   LONGSIZE
+EXPORT(ejtag_debug_buffer_per_cpu)
+       .fill   LONGSIZE * NR_CPUS
+#endif
        .previous
 
        __INIT