Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / include / asm-mips / mipsregs.h
index 2197aa4..5af7517 100644 (file)
@@ -8,7 +8,7 @@
  * Modified for further R[236]000 support by Paul M. Antoine, 1996.
  * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
  * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
- * Copyright (C) 2003  Maciej W. Rozycki
+ * Copyright (C) 2003, 2004  Maciej W. Rozycki
  */
 #ifndef _ASM_MIPSREGS_H
 #define _ASM_MIPSREGS_H
 #define CP0_S1_DERRADDR1  $27
 #define CP0_S1_INTCONTROL $20
 
+/*
+ * Coprocessor 0 Set 2 register names
+ */
+#define CP0_S2_SRSCTL    $12   /* MIPSR2 */
+
+/*
+ * Coprocessor 0 Set 3 register names
+ */
+#define CP0_S3_SRSMAP    $12   /* MIPSR2 */
+
 /*
  *  TX39 Series
  */
 #define ST0_IL                 (_ULCAST_(1) << 23)
 #define ST0_DL                 (_ULCAST_(1) << 24)
 
+/*
+ * Enable the MIPS MDMX and DSP ASEs
+ */
+#define ST0_MX                 0x01000000
+
 /*
  * Bitfields in the TX39 family CP0 Configuration Register 3
  */
 #define R5K_CONF_SE            (_ULCAST_(1) << 12)
 #define R5K_CONF_SS            (_ULCAST_(3) << 20)
 
+/* Bits specific to the RM7000.  */
+#define RM7K_CONF_SE           (_ULCAST_(1) <<  3)
+#define RM7K_CONF_TE           (_ULCAST_(1) << 12)
+#define RM7K_CONF_CLK          (_ULCAST_(1) << 16)
+#define RM7K_CONF_TC           (_ULCAST_(1) << 17)
+#define RM7K_CONF_SI           (_ULCAST_(3) << 20)
+#define RM7K_CONF_SC           (_ULCAST_(1) << 31)
+
 /* Bits specific to the R10000.  */
 #define R10K_CONF_DN           (_ULCAST_(3) <<  3)
 #define R10K_CONF_CT           (_ULCAST_(1) <<  5)
 #define MIPS_CONF_AT           (_ULCAST_(3) << 13)
 #define MIPS_CONF_M            (_ULCAST_(1) << 31)
 
+/*
+ * Bits in the MIPS32/64 PRA coprocessor 0 config registers 1 and above.
+ */
+#define MIPS_CONF1_FP          (_ULCAST_(1) <<  0)
+#define MIPS_CONF1_EP          (_ULCAST_(1) <<  1)
+#define MIPS_CONF1_CA          (_ULCAST_(1) <<  2)
+#define MIPS_CONF1_WR          (_ULCAST_(1) <<  3)
+#define MIPS_CONF1_PC          (_ULCAST_(1) <<  4)
+#define MIPS_CONF1_MD          (_ULCAST_(1) <<  5)
+#define MIPS_CONF1_C2          (_ULCAST_(1) <<  6)
+#define MIPS_CONF1_DA          (_ULCAST_(7) <<  7)
+#define MIPS_CONF1_DL          (_ULCAST_(7) << 10)
+#define MIPS_CONF1_DS          (_ULCAST_(7) << 13)
+#define MIPS_CONF1_IA          (_ULCAST_(7) << 16)
+#define MIPS_CONF1_IL          (_ULCAST_(7) << 19)
+#define MIPS_CONF1_IS          (_ULCAST_(7) << 22)
+#define MIPS_CONF1_TLBS                (_ULCAST_(63)<< 25)
+
+#define MIPS_CONF2_SA          (_ULCAST_(15)<<  0)
+#define MIPS_CONF2_SL          (_ULCAST_(15)<<  4)
+#define MIPS_CONF2_SS          (_ULCAST_(15)<<  8)
+#define MIPS_CONF2_SU          (_ULCAST_(15)<< 12)
+#define MIPS_CONF2_TA          (_ULCAST_(15)<< 16)
+#define MIPS_CONF2_TL          (_ULCAST_(15)<< 20)
+#define MIPS_CONF2_TS          (_ULCAST_(15)<< 24)
+#define MIPS_CONF2_TU          (_ULCAST_(7) << 28)
+
+#define MIPS_CONF3_TL          (_ULCAST_(1) <<  0)
+#define MIPS_CONF3_SM          (_ULCAST_(1) <<  1)
+#define MIPS_CONF3_MT          (_ULCAST_(1) <<  2)
+#define MIPS_CONF3_SP          (_ULCAST_(1) <<  4)
+#define MIPS_CONF3_VINT                (_ULCAST_(1) <<  5)
+#define MIPS_CONF3_VEIC                (_ULCAST_(1) <<  6)
+#define MIPS_CONF3_LPA         (_ULCAST_(1) <<  7)
+#define MIPS_CONF3_DSP         (_ULCAST_(1) << 10)
+
+/*
+ * Bits in the MIPS32/64 coprocessor 1 (FPU) revision register.
+ */
+#define MIPS_FPIR_S            (_ULCAST_(1) << 16)
+#define MIPS_FPIR_D            (_ULCAST_(1) << 17)
+#define MIPS_FPIR_PS           (_ULCAST_(1) << 18)
+#define MIPS_FPIR_3D           (_ULCAST_(1) << 19)
+#define MIPS_FPIR_W            (_ULCAST_(1) << 20)
+#define MIPS_FPIR_L            (_ULCAST_(1) << 21)
+#define MIPS_FPIR_F64          (_ULCAST_(1) << 22)
+
 /*
  * R10000 performance counter definitions.
  *
@@ -621,13 +691,13 @@ do {                                                                      \
        if (sel == 0)                                                   \
                __asm__ __volatile__(                                   \
                        "mtc0\t%z0, " #register "\n\t"                  \
-                       : : "Jr" ((unsigned int)value));                \
+                       : : "Jr" ((unsigned int)(value)));              \
        else                                                            \
                __asm__ __volatile__(                                   \
                        ".set\tmips32\n\t"                              \
                        "mtc0\t%z0, " #register ", " #sel "\n\t"        \
                        ".set\tmips0"                                   \
-                       : : "Jr" ((unsigned int)value));                \
+                       : : "Jr" ((unsigned int)(value)));              \
 } while (0)
 
 #define __write_64bit_c0_register(register, sel, value)                        \
@@ -676,7 +746,7 @@ do {                                                                        \
 do {                                                                   \
        __asm__ __volatile__(                                           \
                "ctc0\t%z0, " #register "\n\t"                          \
-               : : "Jr" ((unsigned int)value));                        \
+               : : "Jr" ((unsigned int)(value)));                      \
 } while (0)
 
 /*
@@ -766,17 +836,44 @@ do {                                                                      \
 #define read_c0_cache()                __read_32bit_c0_register($7, 0) /* TX39xx */
 #define write_c0_cache(val)    __write_32bit_c0_register($7, 0, val)
 
+#define read_c0_badvaddr()     __read_ulong_c0_register($8, 0)
+#define write_c0_badvaddr(val) __write_ulong_c0_register($8, 0, val)
+
 #define read_c0_count()                __read_32bit_c0_register($9, 0)
 #define write_c0_count(val)    __write_32bit_c0_register($9, 0, val)
 
+#define read_c0_count2()       __read_32bit_c0_register($9, 6) /* pnx8550 */
+#define write_c0_count2(val)   __write_32bit_c0_register($9, 6, val)
+
+#define read_c0_count3()       __read_32bit_c0_register($9, 7) /* pnx8550 */
+#define write_c0_count3(val)   __write_32bit_c0_register($9, 7, val)
+
 #define read_c0_entryhi()      __read_ulong_c0_register($10, 0)
 #define write_c0_entryhi(val)  __write_ulong_c0_register($10, 0, val)
 
 #define read_c0_compare()      __read_32bit_c0_register($11, 0)
 #define write_c0_compare(val)  __write_32bit_c0_register($11, 0, val)
 
+#define read_c0_compare2()     __read_32bit_c0_register($11, 6) /* pnx8550 */
+#define write_c0_compare2(val) __write_32bit_c0_register($11, 6, val)
+
+#define read_c0_compare3()     __read_32bit_c0_register($11, 7) /* pnx8550 */
+#define write_c0_compare3(val) __write_32bit_c0_register($11, 7, val)
+
 #define read_c0_status()       __read_32bit_c0_register($12, 0)
+#ifdef CONFIG_MIPS_MT_SMTC
+#define write_c0_status(val)                                           \
+do {                                                                   \
+       __write_32bit_c0_register($12, 0, val);                         \
+       __ehb();                                                        \
+} while (0)
+#else
+/*
+ * Legacy non-SMTC code, which may be hazardous
+ * but which might not support EHB
+ */
 #define write_c0_status(val)   __write_32bit_c0_register($12, 0, val)
+#endif /* CONFIG_MIPS_MT_SMTC */
 
 #define read_c0_cause()                __read_32bit_c0_register($13, 0)
 #define write_c0_cause(val)    __write_32bit_c0_register($13, 0, val)
@@ -790,10 +887,18 @@ do {                                                                      \
 #define read_c0_config1()      __read_32bit_c0_register($16, 1)
 #define read_c0_config2()      __read_32bit_c0_register($16, 2)
 #define read_c0_config3()      __read_32bit_c0_register($16, 3)
+#define read_c0_config4()      __read_32bit_c0_register($16, 4)
+#define read_c0_config5()      __read_32bit_c0_register($16, 5)
+#define read_c0_config6()      __read_32bit_c0_register($16, 6)
+#define read_c0_config7()      __read_32bit_c0_register($16, 7)
 #define write_c0_config(val)   __write_32bit_c0_register($16, 0, val)
 #define write_c0_config1(val)  __write_32bit_c0_register($16, 1, val)
 #define write_c0_config2(val)  __write_32bit_c0_register($16, 2, val)
 #define write_c0_config3(val)  __write_32bit_c0_register($16, 3, val)
+#define write_c0_config4(val)  __write_32bit_c0_register($16, 4, val)
+#define write_c0_config5(val)  __write_32bit_c0_register($16, 5, val)
+#define write_c0_config6(val)  __write_32bit_c0_register($16, 6, val)
+#define write_c0_config7(val)  __write_32bit_c0_register($16, 7, val)
 
 /*
  * The WatchLo register.  There may be upto 8 of them.
@@ -911,12 +1016,31 @@ do {                                                                     \
 #define read_c0_taglo()                __read_32bit_c0_register($28, 0)
 #define write_c0_taglo(val)    __write_32bit_c0_register($28, 0, val)
 
+#define read_c0_dtaglo()       __read_32bit_c0_register($28, 2)
+#define write_c0_dtaglo(val)   __write_32bit_c0_register($28, 2, val)
+
 #define read_c0_taghi()                __read_32bit_c0_register($29, 0)
 #define write_c0_taghi(val)    __write_32bit_c0_register($29, 0, val)
 
 #define read_c0_errorepc()     __read_ulong_c0_register($30, 0)
 #define write_c0_errorepc(val) __write_ulong_c0_register($30, 0, val)
 
+/* MIPSR2 */
+#define read_c0_hwrena()       __read_32bit_c0_register($7,0)
+#define write_c0_hwrena(val)   __write_32bit_c0_register($7, 0, val)
+
+#define read_c0_intctl()       __read_32bit_c0_register($12, 1)
+#define write_c0_intctl(val)   __write_32bit_c0_register($12, 1, val)
+
+#define read_c0_srsctl()       __read_32bit_c0_register($12, 2)
+#define write_c0_srsctl(val)   __write_32bit_c0_register($12, 2, val)
+
+#define read_c0_srsmap()       __read_32bit_c0_register($12, 3)
+#define write_c0_srsmap(val)   __write_32bit_c0_register($12, 3, val)
+
+#define read_c0_ebase()                __read_32bit_c0_register($15,1)
+#define write_c0_ebase(val)    __write_32bit_c0_register($15, 1, val)
+
 /*
  * Macros to access the floating point coprocessor control registers
  */
@@ -930,6 +1054,284 @@ do {                                                                     \
         : "=r" (__res));                                        \
         __res;})
 
+#define rddsp(mask)                                                    \
+({                                                                     \
+       unsigned int __res;                                             \
+                                                                       \
+       __asm__ __volatile__(                                           \
+       "       .set    push                            \n"             \
+       "       .set    noat                            \n"             \
+       "       # rddsp $1, %x1                         \n"             \
+       "       .word   0x7c000cb8 | (%x1 << 16)        \n"             \
+       "       move    %0, $1                          \n"             \
+       "       .set    pop                             \n"             \
+       : "=r" (__res)                                                  \
+       : "i" (mask));                                                  \
+       __res;                                                          \
+})
+
+#define wrdsp(val, mask)                                               \
+do {                                                                   \
+       __asm__ __volatile__(                                           \
+       "       .set    push                                    \n"     \
+       "       .set    noat                                    \n"     \
+       "       move    $1, %0                                  \n"     \
+       "       # wrdsp $1, %x1                                 \n"     \
+       "       .word   0x7c2004f8 | (%x1 << 11)                \n"     \
+       "       .set    pop                                     \n"     \
+        :                                                              \
+       : "r" (val), "i" (mask));                                       \
+} while (0)
+
+#if 0  /* Need DSP ASE capable assembler ... */
+#define mflo0() ({ long mflo0; __asm__("mflo %0, $ac0" : "=r" (mflo0)); mflo0;})
+#define mflo1() ({ long mflo1; __asm__("mflo %0, $ac1" : "=r" (mflo1)); mflo1;})
+#define mflo2() ({ long mflo2; __asm__("mflo %0, $ac2" : "=r" (mflo2)); mflo2;})
+#define mflo3() ({ long mflo3; __asm__("mflo %0, $ac3" : "=r" (mflo3)); mflo3;})
+
+#define mfhi0() ({ long mfhi0; __asm__("mfhi %0, $ac0" : "=r" (mfhi0)); mfhi0;})
+#define mfhi1() ({ long mfhi1; __asm__("mfhi %0, $ac1" : "=r" (mfhi1)); mfhi1;})
+#define mfhi2() ({ long mfhi2; __asm__("mfhi %0, $ac2" : "=r" (mfhi2)); mfhi2;})
+#define mfhi3() ({ long mfhi3; __asm__("mfhi %0, $ac3" : "=r" (mfhi3)); mfhi3;})
+
+#define mtlo0(x) __asm__("mtlo %0, $ac0" ::"r" (x))
+#define mtlo1(x) __asm__("mtlo %0, $ac1" ::"r" (x))
+#define mtlo2(x) __asm__("mtlo %0, $ac2" ::"r" (x))
+#define mtlo3(x) __asm__("mtlo %0, $ac3" ::"r" (x))
+
+#define mthi0(x) __asm__("mthi %0, $ac0" ::"r" (x))
+#define mthi1(x) __asm__("mthi %0, $ac1" ::"r" (x))
+#define mthi2(x) __asm__("mthi %0, $ac2" ::"r" (x))
+#define mthi3(x) __asm__("mthi %0, $ac3" ::"r" (x))
+
+#else
+
+#define mfhi0()                                                                \
+({                                                                     \
+       unsigned long __treg;                                           \
+                                                                       \
+       __asm__ __volatile__(                                           \
+       "       .set    push                    \n"                     \
+       "       .set    noat                    \n"                     \
+       "       # mfhi  %0, $ac0                \n"                     \
+       "       .word   0x00000810              \n"                     \
+       "       move    %0, $1                  \n"                     \
+       "       .set    pop                     \n"                     \
+       : "=r" (__treg));                                               \
+       __treg;                                                         \
+})
+
+#define mfhi1()                                                                \
+({                                                                     \
+       unsigned long __treg;                                           \
+                                                                       \
+       __asm__ __volatile__(                                           \
+       "       .set    push                    \n"                     \
+       "       .set    noat                    \n"                     \
+       "       # mfhi  %0, $ac1                \n"                     \
+       "       .word   0x00200810              \n"                     \
+       "       move    %0, $1                  \n"                     \
+       "       .set    pop                     \n"                     \
+       : "=r" (__treg));                                               \
+       __treg;                                                         \
+})
+
+#define mfhi2()                                                                \
+({                                                                     \
+       unsigned long __treg;                                           \
+                                                                       \
+       __asm__ __volatile__(                                           \
+       "       .set    push                    \n"                     \
+       "       .set    noat                    \n"                     \
+       "       # mfhi  %0, $ac2                \n"                     \
+       "       .word   0x00400810              \n"                     \
+       "       move    %0, $1                  \n"                     \
+       "       .set    pop                     \n"                     \
+       : "=r" (__treg));                                               \
+       __treg;                                                         \
+})
+
+#define mfhi3()                                                                \
+({                                                                     \
+       unsigned long __treg;                                           \
+                                                                       \
+       __asm__ __volatile__(                                           \
+       "       .set    push                    \n"                     \
+       "       .set    noat                    \n"                     \
+       "       # mfhi  %0, $ac3                \n"                     \
+       "       .word   0x00600810              \n"                     \
+       "       move    %0, $1                  \n"                     \
+       "       .set    pop                     \n"                     \
+       : "=r" (__treg));                                               \
+       __treg;                                                         \
+})
+
+#define mflo0()                                                                \
+({                                                                     \
+       unsigned long __treg;                                           \
+                                                                       \
+       __asm__ __volatile__(                                           \
+       "       .set    push                    \n"                     \
+       "       .set    noat                    \n"                     \
+       "       # mflo  %0, $ac0                \n"                     \
+       "       .word   0x00000812              \n"                     \
+       "       move    %0, $1                  \n"                     \
+       "       .set    pop                     \n"                     \
+       : "=r" (__treg));                                               \
+       __treg;                                                         \
+})
+
+#define mflo1()                                                                \
+({                                                                     \
+       unsigned long __treg;                                           \
+                                                                       \
+       __asm__ __volatile__(                                           \
+       "       .set    push                    \n"                     \
+       "       .set    noat                    \n"                     \
+       "       # mflo  %0, $ac1                \n"                     \
+       "       .word   0x00200812              \n"                     \
+       "       move    %0, $1                  \n"                     \
+       "       .set    pop                     \n"                     \
+       : "=r" (__treg));                                               \
+       __treg;                                                         \
+})
+
+#define mflo2()                                                                \
+({                                                                     \
+       unsigned long __treg;                                           \
+                                                                       \
+       __asm__ __volatile__(                                           \
+       "       .set    push                    \n"                     \
+       "       .set    noat                    \n"                     \
+       "       # mflo  %0, $ac2                \n"                     \
+       "       .word   0x00400812              \n"                     \
+       "       move    %0, $1                  \n"                     \
+       "       .set    pop                     \n"                     \
+       : "=r" (__treg));                                               \
+       __treg;                                                         \
+})
+
+#define mflo3()                                                                \
+({                                                                     \
+       unsigned long __treg;                                           \
+                                                                       \
+       __asm__ __volatile__(                                           \
+       "       .set    push                    \n"                     \
+       "       .set    noat                    \n"                     \
+       "       # mflo  %0, $ac3                \n"                     \
+       "       .word   0x00600812              \n"                     \
+       "       move    %0, $1                  \n"                     \
+       "       .set    pop                     \n"                     \
+       : "=r" (__treg));                                               \
+       __treg;                                                         \
+})
+
+#define mthi0(x)                                                       \
+do {                                                                   \
+       __asm__ __volatile__(                                           \
+       "       .set    push                                    \n"     \
+       "       .set    noat                                    \n"     \
+       "       move    $1, %0                                  \n"     \
+       "       # mthi  $1, $ac0                                \n"     \
+       "       .word   0x00200011                              \n"     \
+       "       .set    pop                                     \n"     \
+       :                                                               \
+       : "r" (x));                                                     \
+} while (0)
+
+#define mthi1(x)                                                       \
+do {                                                                   \
+       __asm__ __volatile__(                                           \
+       "       .set    push                                    \n"     \
+       "       .set    noat                                    \n"     \
+       "       move    $1, %0                                  \n"     \
+       "       # mthi  $1, $ac1                                \n"     \
+       "       .word   0x00200811                              \n"     \
+       "       .set    pop                                     \n"     \
+       :                                                               \
+       : "r" (x));                                                     \
+} while (0)
+
+#define mthi2(x)                                                       \
+do {                                                                   \
+       __asm__ __volatile__(                                           \
+       "       .set    push                                    \n"     \
+       "       .set    noat                                    \n"     \
+       "       move    $1, %0                                  \n"     \
+       "       # mthi  $1, $ac2                                \n"     \
+       "       .word   0x00201011                              \n"     \
+       "       .set    pop                                     \n"     \
+       :                                                               \
+       : "r" (x));                                                     \
+} while (0)
+
+#define mthi3(x)                                                       \
+do {                                                                   \
+       __asm__ __volatile__(                                           \
+       "       .set    push                                    \n"     \
+       "       .set    noat                                    \n"     \
+       "       move    $1, %0                                  \n"     \
+       "       # mthi  $1, $ac3                                \n"     \
+       "       .word   0x00201811                              \n"     \
+       "       .set    pop                                     \n"     \
+       :                                                               \
+       : "r" (x));                                                     \
+} while (0)
+
+#define mtlo0(x)                                                       \
+do {                                                                   \
+       __asm__ __volatile__(                                           \
+       "       .set    push                                    \n"     \
+       "       .set    noat                                    \n"     \
+       "       move    $1, %0                                  \n"     \
+       "       # mtlo  $1, $ac0                                \n"     \
+       "       .word   0x00200013                              \n"     \
+       "       .set    pop                                     \n"     \
+       :                                                               \
+       : "r" (x));                                                     \
+} while (0)
+
+#define mtlo1(x)                                                       \
+do {                                                                   \
+       __asm__ __volatile__(                                           \
+       "       .set    push                                    \n"     \
+       "       .set    noat                                    \n"     \
+       "       move    $1, %0                                  \n"     \
+       "       # mtlo  $1, $ac1                                \n"     \
+       "       .word   0x00200813                              \n"     \
+       "       .set    pop                                     \n"     \
+       :                                                               \
+       : "r" (x));                                                     \
+} while (0)
+
+#define mtlo2(x)                                                       \
+do {                                                                   \
+       __asm__ __volatile__(                                           \
+       "       .set    push                                    \n"     \
+       "       .set    noat                                    \n"     \
+       "       move    $1, %0                                  \n"     \
+       "       # mtlo  $1, $ac2                                \n"     \
+       "       .word   0x00201013                              \n"     \
+       "       .set    pop                                     \n"     \
+       :                                                               \
+       : "r" (x));                                                     \
+} while (0)
+
+#define mtlo3(x)                                                       \
+do {                                                                   \
+       __asm__ __volatile__(                                           \
+       "       .set    push                                    \n"     \
+       "       .set    noat                                    \n"     \
+       "       move    $1, %0                                  \n"     \
+       "       # mtlo  $1, $ac3                                \n"     \
+       "       .word   0x00201813                              \n"     \
+       "       .set    pop                                     \n"     \
+       :                                                               \
+       : "r" (x));                                                     \
+} while (0)
+
+#endif
+
 /*
  * TLB operations.
  *
@@ -970,15 +1372,119 @@ static inline void tlb_write_random(void)
 /*
  * Manipulate bits in a c0 register.
  */
+#ifndef CONFIG_MIPS_MT_SMTC
+/*
+ * SMTC Linux requires shutting-down microthread scheduling
+ * during CP0 register read-modify-write sequences.
+ */
+#define __BUILD_SET_C0(name)                                   \
+static inline unsigned int                                     \
+set_c0_##name(unsigned int set)                                        \
+{                                                              \
+       unsigned int res;                                       \
+                                                               \
+       res = read_c0_##name();                                 \
+       res |= set;                                             \
+       write_c0_##name(res);                                   \
+                                                               \
+       return res;                                             \
+}                                                              \
+                                                               \
+static inline unsigned int                                     \
+clear_c0_##name(unsigned int clear)                            \
+{                                                              \
+       unsigned int res;                                       \
+                                                               \
+       res = read_c0_##name();                                 \
+       res &= ~clear;                                          \
+       write_c0_##name(res);                                   \
+                                                               \
+       return res;                                             \
+}                                                              \
+                                                               \
+static inline unsigned int                                     \
+change_c0_##name(unsigned int change, unsigned int new)                \
+{                                                              \
+       unsigned int res;                                       \
+                                                               \
+       res = read_c0_##name();                                 \
+       res &= ~change;                                         \
+       res |= (new & change);                                  \
+       write_c0_##name(res);                                   \
+                                                               \
+       return res;                                             \
+}
+
+#else /* SMTC versions that manage MT scheduling */
+
+#include <asm/interrupt.h>
+
+/*
+ * This is a duplicate of dmt() in mipsmtregs.h to avoid problems with
+ * header file recursion.
+ */
+static inline unsigned int __dmt(void)
+{
+       int res;
+
+       __asm__ __volatile__(
+       "       .set    push                                            \n"
+       "       .set    mips32r2                                        \n"
+       "       .set    noat                                            \n"
+       "       .word   0x41610BC1                      # dmt $1        \n"
+       "       ehb                                                     \n"
+       "       move    %0, $1                                          \n"
+       "       .set    pop                                             \n"
+       : "=r" (res));
+
+       instruction_hazard();
+
+       return res;
+}
+
+#define __VPECONTROL_TE_SHIFT  15
+#define __VPECONTROL_TE                (1UL << __VPECONTROL_TE_SHIFT)
+
+#define __EMT_ENABLE           __VPECONTROL_TE
+
+static inline void __emt(unsigned int previous)
+{
+       if ((previous & __EMT_ENABLE))
+               __asm__ __volatile__(
+               "       .set    noreorder                               \n"
+               "       .set    mips32r2                                \n"
+               "       .word   0x41600be1              # emt           \n"
+               "       ehb                                             \n"
+               "       .set    mips0                                   \n"
+               "       .set    reorder                                 \n");
+}
+
+static inline void __ehb(void)
+{
+       __asm__ __volatile__(
+       "       ehb                                                     \n");
+}
+
+/*
+ * Note that local_irq_save/restore affect TC-specific IXMT state,
+ * not Status.IE as in non-SMTC kernel.
+ */
+
 #define __BUILD_SET_C0(name)                                   \
 static inline unsigned int                                     \
 set_c0_##name(unsigned int set)                                        \
 {                                                              \
        unsigned int res;                                       \
+       unsigned int omt;                                       \
+       unsigned int flags;                                     \
                                                                \
+       local_irq_save(flags);                                  \
+       omt = __dmt();                                          \
        res = read_c0_##name();                                 \
        res |= set;                                             \
        write_c0_##name(res);                                   \
+       __emt(omt);                                             \
+       local_irq_restore(flags);                               \
                                                                \
        return res;                                             \
 }                                                              \
@@ -987,10 +1493,16 @@ static inline unsigned int                                       \
 clear_c0_##name(unsigned int clear)                            \
 {                                                              \
        unsigned int res;                                       \
+       unsigned int omt;                                       \
+       unsigned int flags;                                     \
                                                                \
+       local_irq_save(flags);                                  \
+       omt = __dmt();                                          \
        res = read_c0_##name();                                 \
        res &= ~clear;                                          \
        write_c0_##name(res);                                   \
+       __emt(omt);                                             \
+       local_irq_restore(flags);                               \
                                                                \
        return res;                                             \
 }                                                              \
@@ -999,19 +1511,29 @@ static inline unsigned int                                       \
 change_c0_##name(unsigned int change, unsigned int new)                \
 {                                                              \
        unsigned int res;                                       \
+       unsigned int omt;                                       \
+       unsigned int flags;                                     \
                                                                \
+       local_irq_save(flags);                                  \
+                                                               \
+       omt = __dmt();                                          \
        res = read_c0_##name();                                 \
        res &= ~change;                                         \
        res |= (new & change);                                  \
        write_c0_##name(res);                                   \
+       __emt(omt);                                             \
+       local_irq_restore(flags);                               \
                                                                \
        return res;                                             \
 }
+#endif
 
 __BUILD_SET_C0(status)
 __BUILD_SET_C0(cause)
 __BUILD_SET_C0(config)
 __BUILD_SET_C0(intcontrol)
+__BUILD_SET_C0(intctl)
+__BUILD_SET_C0(srsmap)
 
 #endif /* !__ASSEMBLY__ */