1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 #include <linux/linkage.h>
  16 #include <asm/asm-offsets.h>
  17 #include <asm/asmmacro.h>
  18 #include <asm/processor.h>
  19 #include <asm/coprocessor.h>
  20 #include <asm/thread_info.h>
  21 #include <asm/asm-uaccess.h>
  22 #include <asm/unistd.h>
  23 #include <asm/ptrace.h>
  24 #include <asm/current.h>
  25 #include <asm/pgtable.h>
  26 #include <asm/page.h>
  27 #include <asm/signal.h>
  28 #include <asm/tlbflush.h>
  29 
  30 #if XTENSA_HAVE_COPROCESSORS
  31 
  32 
  33 
  34 
  35 
  36 #define SAVE_CP_REGS(x)                                                 \
  37         .if XTENSA_HAVE_COPROCESSOR(x);                                 \
  38                 .align 4;                                               \
  39         .Lsave_cp_regs_cp##x:                                           \
  40                 xchal_cp##x##_store a2 a4 a5 a6 a7;                     \
  41                 jx      a0;                                             \
  42         .endif
  43 
  44 #define SAVE_CP_REGS_TAB(x)                                             \
  45         .if XTENSA_HAVE_COPROCESSOR(x);                                 \
  46                 .long .Lsave_cp_regs_cp##x;                             \
  47         .else;                                                          \
  48                 .long 0;                                                \
  49         .endif;                                                         \
  50         .long THREAD_XTREGS_CP##x
  51 
  52 
  53 #define LOAD_CP_REGS(x)                                                 \
  54         .if XTENSA_HAVE_COPROCESSOR(x);                                 \
  55                 .align 4;                                               \
  56         .Lload_cp_regs_cp##x:                                           \
  57                 xchal_cp##x##_load a2 a4 a5 a6 a7;                      \
  58                 jx      a0;                                             \
  59         .endif
  60 
  61 #define LOAD_CP_REGS_TAB(x)                                             \
  62         .if XTENSA_HAVE_COPROCESSOR(x);                                 \
  63                 .long .Lload_cp_regs_cp##x;                             \
  64         .else;                                                          \
  65                 .long 0;                                                \
  66         .endif;                                                         \
  67         .long THREAD_XTREGS_CP##x
  68 
  69         SAVE_CP_REGS(0)
  70         SAVE_CP_REGS(1)
  71         SAVE_CP_REGS(2)
  72         SAVE_CP_REGS(3)
  73         SAVE_CP_REGS(4)
  74         SAVE_CP_REGS(5)
  75         SAVE_CP_REGS(6)
  76         SAVE_CP_REGS(7)
  77 
  78         LOAD_CP_REGS(0)
  79         LOAD_CP_REGS(1)
  80         LOAD_CP_REGS(2)
  81         LOAD_CP_REGS(3)
  82         LOAD_CP_REGS(4)
  83         LOAD_CP_REGS(5)
  84         LOAD_CP_REGS(6)
  85         LOAD_CP_REGS(7)
  86 
  87         .section ".rodata", "a"
  88         .align 4
  89 .Lsave_cp_regs_jump_table:
  90         SAVE_CP_REGS_TAB(0)
  91         SAVE_CP_REGS_TAB(1)
  92         SAVE_CP_REGS_TAB(2)
  93         SAVE_CP_REGS_TAB(3)
  94         SAVE_CP_REGS_TAB(4)
  95         SAVE_CP_REGS_TAB(5)
  96         SAVE_CP_REGS_TAB(6)
  97         SAVE_CP_REGS_TAB(7)
  98 
  99 .Lload_cp_regs_jump_table:
 100         LOAD_CP_REGS_TAB(0)
 101         LOAD_CP_REGS_TAB(1)
 102         LOAD_CP_REGS_TAB(2)
 103         LOAD_CP_REGS_TAB(3)
 104         LOAD_CP_REGS_TAB(4)
 105         LOAD_CP_REGS_TAB(5)
 106         LOAD_CP_REGS_TAB(6)
 107         LOAD_CP_REGS_TAB(7)
 108 
 109         .previous
 110 
 111 
 112 
 113 
 114 
 115 
 116 
 117 
 118 
 119 
 120 
 121 
 122 
 123 ENTRY(coprocessor_flush)
 124 
 125         
 126         abi_entry(4)
 127 
 128         s32i    a0, a1, 0
 129         movi    a0, .Lsave_cp_regs_jump_table
 130         addx8   a3, a3, a0
 131         l32i    a4, a3, 4
 132         l32i    a3, a3, 0
 133         add     a2, a2, a4
 134         beqz    a3, 1f
 135         callx0  a3
 136 1:      l32i    a0, a1, 0
 137 
 138         abi_ret(4)
 139 
 140 ENDPROC(coprocessor_flush)
 141 
 142 
 143 
 144 
 145 
 146 
 147 
 148 
 149 
 150 
 151 
 152 
 153 
 154 
 155 
 156 ENTRY(fast_coprocessor_double)
 157 
 158         wsr     a0, excsave1
 159         call0   unrecoverable_exception
 160 
 161 ENDPROC(fast_coprocessor_double)
 162 
 163 ENTRY(fast_coprocessor)
 164 
 165         
 166 
 167         s32i    a3, a2, PT_AREG3
 168         rsr     a3, sar
 169         s32i    a1, a2, PT_AREG1
 170         s32i    a3, a2, PT_SAR
 171         mov     a1, a2
 172         rsr     a2, depc
 173         s32i    a2, a1, PT_AREG2
 174 
 175         
 176 
 177 
 178 
 179         s32i    a4, a1, PT_AREG4
 180         s32i    a5, a1, PT_AREG5
 181         s32i    a6, a1, PT_AREG6
 182 
 183         
 184 
 185         rsr     a3, exccause
 186         addi    a3, a3, -EXCCAUSE_COPROCESSOR0_DISABLED
 187 
 188         
 189 
 190         ssl     a3                      # SAR: 32 - coprocessor_number
 191         movi    a2, 1
 192         rsr     a0, cpenable
 193         sll     a2, a2
 194         or      a0, a0, a2
 195         wsr     a0, cpenable
 196         rsync
 197 
 198         
 199 
 200         movi    a0, coprocessor_owner   # list of owners
 201         addx4   a0, a3, a0              # entry for CP
 202         l32i    a4, a0, 0
 203 
 204         beqz    a4, 1f                  # skip 'save' if no previous owner
 205 
 206         
 207 
 208         l32i    a5, a4, THREAD_CPENABLE
 209         xor     a5, a5, a2              # (1 << cp-id) still in a2
 210         s32i    a5, a4, THREAD_CPENABLE
 211 
 212         
 213 
 214 
 215 
 216 
 217         movi    a5, .Lsave_cp_regs_jump_table
 218         movi    a0, 2f                  # a0: 'return' address
 219         addx8   a3, a3, a5              # a3: coprocessor number
 220         l32i    a2, a3, 4               # a2: xtregs offset
 221         l32i    a3, a3, 0               # a3: jump address
 222         add     a2, a2, a4
 223         jx      a3
 224 
 225         
 226 
 227 2:      rsr     a3, exccause
 228         addi    a3, a3, -EXCCAUSE_COPROCESSOR0_DISABLED
 229         movi    a0, coprocessor_owner
 230         addx4   a0, a3, a0
 231 
 232         
 233 
 234 1:      GET_THREAD_INFO (a4, a1)
 235         s32i    a4, a0, 0
 236 
 237         
 238 
 239         movi    a5, .Lload_cp_regs_jump_table
 240         movi    a0, 1f
 241         addx8   a3, a3, a5
 242         l32i    a2, a3, 4               # a2: xtregs offset
 243         l32i    a3, a3, 0               # a3: jump address
 244         add     a2, a2, a4
 245         jx      a3
 246 
 247         
 248 
 249 1:      l32i    a6, a1, PT_AREG6
 250         l32i    a5, a1, PT_AREG5
 251         l32i    a4, a1, PT_AREG4
 252 
 253         l32i    a0, a1, PT_SAR
 254         l32i    a3, a1, PT_AREG3
 255         l32i    a2, a1, PT_AREG2
 256         wsr     a0, sar
 257         l32i    a0, a1, PT_AREG0
 258         l32i    a1, a1, PT_AREG1
 259 
 260         rfe
 261 
 262 ENDPROC(fast_coprocessor)
 263 
 264         .data
 265 
 266 ENTRY(coprocessor_owner)
 267 
 268         .fill XCHAL_CP_MAX, 4, 0
 269 
 270 END(coprocessor_owner)
 271 
 272 #endif