MIPS: Hang if run on a secondary CPU
authorPaul Burton <paul.burton@imgtec.com>
Wed, 21 Sep 2016 13:59:54 +0000 (14:59 +0100)
committerDaniel Schwierzeck <daniel.schwierzeck@gmail.com>
Wed, 21 Sep 2016 15:04:53 +0000 (17:04 +0200)
Some systems are configured such that multiple CPUs begin running from
their reset vector following a system reset. If this occurs then U-Boot
will be run on multiple CPUs simultaneously, which causes all sorts of
issues as the multiple instances of U-Boot clobber each other.

Prevent this from happening by simply hanging with an infinite loop if
we run on a CPU whose ID, as determined by GlobalNumber or EBase.CPUNum
as appropriate, is non-zero.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
arch/mips/cpu/start.S
arch/mips/include/asm/mipsregs.h

index cbc02fa9fe0ddce156be9ca808ac5be83ddde2aa..3f0fc125475271835456db3490bd47a61a3dbb1b 100644 (file)
@@ -108,9 +108,28 @@ ENTRY(_start)
 
        .align 4
 reset:
+#if __mips_isa_rev >= 6
+       mfc0    t0, CP0_CONFIG, 5
+       and     t0, t0, MIPS_CONF5_VP
+       beqz    t0, 1f
+        nop
+
+       b       2f
+        mfc0   t0, CP0_GLOBALNUMBER
+#endif
+
+1:     mfc0    t0, CP0_EBASE
+       and     t0, t0, EBASE_CPUNUM
+
+       /* Hang if this isn't the first CPU in the system */
+2:     beqz    t0, 4f
+        nop
+3:     wait
+       b       3b
+        nop
 
        /* Clear watch registers */
-       MTC0    zero, CP0_WATCHLO
+4:     MTC0    zero, CP0_WATCHLO
        mtc0    zero, CP0_WATCHHI
 
        /* WP(Watch Pending), SW0/1 should be cleared */
index b4c2dff4835f7c79ab4eea6743cf5b1d5f75aedf..9ab506361e7897fb76ad0c8cdd37ebf3e58afc7a 100644 (file)
@@ -39,6 +39,7 @@
 #define CP0_ENTRYLO0 $2
 #define CP0_ENTRYLO1 $3
 #define CP0_CONF $3
+#define CP0_GLOBALNUMBER $3, 1
 #define CP0_CONTEXT $4
 #define CP0_PAGEMASK $5
 #define CP0_WIRED $6
 #define CAUSEB_BD              31
 #define CAUSEF_BD              (_ULCAST_(1)   << 31)
 
+/*
+ * Bits in the coprocessor 0 EBase register.
+ */
+#define EBASE_CPUNUM           0x3ff
+
 /*
  * Bits in the coprocessor 0 config register.
  */
 #define MIPS_CONF5_MRP         (_ULCAST_(1) << 3)
 #define MIPS_CONF5_LLB         (_ULCAST_(1) << 4)
 #define MIPS_CONF5_MVH         (_ULCAST_(1) << 5)
+#define MIPS_CONF5_VP          (_ULCAST_(1) << 7)
 #define MIPS_CONF5_FRE         (_ULCAST_(1) << 8)
 #define MIPS_CONF5_UFE         (_ULCAST_(1) << 9)
 #define MIPS_CONF5_L2C         (_ULCAST_(1) << 10)