| 1 | /////////////////////////////////////////////////////////////////////////// | 
|---|
| 2 | // File     : utils.c | 
|---|
| 3 | // Date     : 18/10/2013 | 
|---|
| 4 | // Author   : alain greiner | 
|---|
| 5 | // Copyright (c) UPMC-LIP6 | 
|---|
| 6 | /////////////////////////////////////////////////////////////////////////// | 
|---|
| 7 | // The utils.c and utils.h files are part of the GIET-VM nano-kernel. | 
|---|
| 8 | /////////////////////////////////////////////////////////////////////////// | 
|---|
| 9 |  | 
|---|
| 10 | #include <utils.h> | 
|---|
| 11 | #include <tty0.h> | 
|---|
| 12 | #include <giet_config.h> | 
|---|
| 13 | #include <hard_config.h> | 
|---|
| 14 | #include <mapping_info.h> | 
|---|
| 15 | #include <tty_driver.h> | 
|---|
| 16 | #include <ctx_handler.h> | 
|---|
| 17 |  | 
|---|
| 18 | // This variable is allocated in the boot.c file or in kernel_init.c file | 
|---|
| 19 | extern static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX]; | 
|---|
| 20 |  | 
|---|
| 21 | /////////////////////////////////////////////////////////////////////////// | 
|---|
| 22 | //         CP0 registers access functions | 
|---|
| 23 | /////////////////////////////////////////////////////////////////////////// | 
|---|
| 24 |  | 
|---|
| 25 | ///////////////////////// | 
|---|
| 26 | unsigned int _get_sched()  | 
|---|
| 27 | { | 
|---|
| 28 |     unsigned int ret; | 
|---|
| 29 |     asm volatile( "mfc0      %0,     $4,2    \n"  | 
|---|
| 30 |                   : "=r"(ret) ); | 
|---|
| 31 |     return ret; | 
|---|
| 32 | } | 
|---|
| 33 | /////////////////////// | 
|---|
| 34 | unsigned int _get_epc()  | 
|---|
| 35 | { | 
|---|
| 36 |     unsigned int ret; | 
|---|
| 37 |     asm volatile( "mfc0      %0,    $14     \n" | 
|---|
| 38 |                   : "=r"(ret) ); | 
|---|
| 39 |     return ret; | 
|---|
| 40 | } | 
|---|
| 41 | //////////////////////// | 
|---|
| 42 | unsigned int _get_bvar()  | 
|---|
| 43 | { | 
|---|
| 44 |     unsigned int ret; | 
|---|
| 45 |     asm volatile( "mfc0      %0,    $8     \n" | 
|---|
| 46 |                   : "=r"(ret)); | 
|---|
| 47 |     return ret; | 
|---|
| 48 | } | 
|---|
| 49 | ////////////////////// | 
|---|
| 50 | unsigned int _get_cr()  | 
|---|
| 51 | { | 
|---|
| 52 |     unsigned int ret; | 
|---|
| 53 |     asm volatile( "mfc0      %0,    $13    \n" | 
|---|
| 54 |                   : "=r"(ret)); | 
|---|
| 55 |     return ret; | 
|---|
| 56 | } | 
|---|
| 57 | ////////////////////// | 
|---|
| 58 | unsigned int _get_sr()  | 
|---|
| 59 | { | 
|---|
| 60 |     unsigned int ret; | 
|---|
| 61 |     asm volatile( "mfc0      %0,     $12   \n" | 
|---|
| 62 |                   : "=r"(ret)); | 
|---|
| 63 |     return ret; | 
|---|
| 64 | } | 
|---|
| 65 | ////////////////////////// | 
|---|
| 66 | unsigned int _get_procid()  | 
|---|
| 67 | { | 
|---|
| 68 |     unsigned int ret; | 
|---|
| 69 |     asm volatile ( "mfc0     %0,     $15, 1  \n" | 
|---|
| 70 |                    :"=r" (ret) ); | 
|---|
| 71 |     return (ret & 0xFFF); | 
|---|
| 72 | } | 
|---|
| 73 | //////////////////////////// | 
|---|
| 74 | unsigned int _get_proctime()  | 
|---|
| 75 | { | 
|---|
| 76 |     unsigned int ret; | 
|---|
| 77 |     asm volatile ( "mfc0     %0,     $9      \n" | 
|---|
| 78 |                    :"=r" (ret) ); | 
|---|
| 79 |     return ret; | 
|---|
| 80 | } | 
|---|
| 81 |  | 
|---|
| 82 | ///////////////////////////////////////////// | 
|---|
| 83 | void _it_disable( unsigned int * save_sr_ptr)  | 
|---|
| 84 | { | 
|---|
| 85 |     unsigned int sr = 0; | 
|---|
| 86 |     asm volatile( "li      $3,        0xFFFFFFFE    \n" | 
|---|
| 87 |                   "mfc0    %0,        $12           \n" | 
|---|
| 88 |                   "and     $3,        $3,   %0      \n"   | 
|---|
| 89 |                   "mtc0    $3,        $12           \n"  | 
|---|
| 90 |                   : "+r"(sr) | 
|---|
| 91 |                   : | 
|---|
| 92 |                   : "$3" ); | 
|---|
| 93 |     *save_sr_ptr = sr; | 
|---|
| 94 | } | 
|---|
| 95 | ////////////////////////////////////////////// | 
|---|
| 96 | void _it_restore( unsigned int * save_sr_ptr )  | 
|---|
| 97 | { | 
|---|
| 98 |     unsigned int sr = *save_sr_ptr; | 
|---|
| 99 |     asm volatile( "mtc0    %0,        $12           \n"  | 
|---|
| 100 |                   : | 
|---|
| 101 |                   : "r"(sr) | 
|---|
| 102 |                   : "memory" ); | 
|---|
| 103 | } | 
|---|
| 104 |  | 
|---|
| 105 | ///////////////////////////////// | 
|---|
| 106 | void _set_sched(unsigned int val)  | 
|---|
| 107 | { | 
|---|
| 108 |     asm volatile ( "mtc0     %0,     $4, 2          \n" | 
|---|
| 109 |                    : | 
|---|
| 110 |                    :"r" (val) ); | 
|---|
| 111 | } | 
|---|
| 112 | ////////////////////////////// | 
|---|
| 113 | void _set_sr(unsigned int val)  | 
|---|
| 114 | { | 
|---|
| 115 |     asm volatile ( "mtc0     %0,     $12            \n" | 
|---|
| 116 |                    : | 
|---|
| 117 |                    :"r" (val) ); | 
|---|
| 118 | } | 
|---|
| 119 |  | 
|---|
| 120 |  | 
|---|
| 121 | /////////////////////////////////////////////////////////////////////////// | 
|---|
| 122 | //         CP2 registers access functions | 
|---|
| 123 | /////////////////////////////////////////////////////////////////////////// | 
|---|
| 124 |  | 
|---|
| 125 | //////////////////////////// | 
|---|
| 126 | unsigned int _get_mmu_ptpr()  | 
|---|
| 127 | { | 
|---|
| 128 |     unsigned int ret; | 
|---|
| 129 |     asm volatile( "mfc2      %0,     $0      \n" | 
|---|
| 130 |                   : "=r"(ret) ); | 
|---|
| 131 |     return ret; | 
|---|
| 132 | } | 
|---|
| 133 | //////////////////////////// | 
|---|
| 134 | unsigned int _get_mmu_mode()  | 
|---|
| 135 | { | 
|---|
| 136 |     unsigned int ret; | 
|---|
| 137 |     asm volatile( "mfc2      %0,     $1      \n" | 
|---|
| 138 |                   : "=r"(ret) ); | 
|---|
| 139 |     return ret; | 
|---|
| 140 | } | 
|---|
| 141 | //////////////////////////////////// | 
|---|
| 142 | void _set_mmu_ptpr(unsigned int val)  | 
|---|
| 143 | { | 
|---|
| 144 |     asm volatile ( "mtc2     %0,     $0      \n" | 
|---|
| 145 |                    : | 
|---|
| 146 |                    :"r" (val) | 
|---|
| 147 |                    :"memory" ); | 
|---|
| 148 | } | 
|---|
| 149 | //////////////////////////////////// | 
|---|
| 150 | void _set_mmu_mode(unsigned int val)  | 
|---|
| 151 | { | 
|---|
| 152 |     asm volatile ( "mtc2     %0,     $1      \n" | 
|---|
| 153 |                    : | 
|---|
| 154 |                    :"r" (val) | 
|---|
| 155 |                    :"memory" ); | 
|---|
| 156 | } | 
|---|
| 157 | //////////////////////////////////////////// | 
|---|
| 158 | void _set_mmu_dcache_inval(unsigned int val)  | 
|---|
| 159 | { | 
|---|
| 160 |     asm volatile ( "mtc2     %0,     $7      \n" | 
|---|
| 161 |                    : | 
|---|
| 162 |                    :"r" (val) | 
|---|
| 163 |                    :"memory" ); | 
|---|
| 164 | } | 
|---|
| 165 |  | 
|---|
| 166 |  | 
|---|
| 167 | /////////////////////////////////////////////////////////////////////////// | 
|---|
| 168 | //          Physical addressing related functions | 
|---|
| 169 | /////////////////////////////////////////////////////////////////////////// | 
|---|
| 170 |  | 
|---|
| 171 | /////////////////////////////////////////////////////// | 
|---|
| 172 | unsigned int _physical_read( unsigned long long paddr )  | 
|---|
| 173 | { | 
|---|
| 174 |     unsigned int value; | 
|---|
| 175 |     unsigned int lsb = (unsigned int) paddr; | 
|---|
| 176 |     unsigned int msb = (unsigned int) (paddr >> 32); | 
|---|
| 177 |     unsigned int sr; | 
|---|
| 178 |  | 
|---|
| 179 |     _it_disable(&sr); | 
|---|
| 180 |  | 
|---|
| 181 |     asm volatile( "mfc2   $2,     $1            \n"  /* $2 <= MMU_MODE   */ | 
|---|
| 182 |                   "andi   $3,     $2,     0xb   \n" | 
|---|
| 183 |                   "mtc2   $3,     $1            \n"  /* DTLB off         */     | 
|---|
| 184 |  | 
|---|
| 185 |                   "mtc2   %2,     $24           \n"  /* PADDR_EXT <= msb */    | 
|---|
| 186 |                   "lw     %0,     0(%1)         \n"  /* value <= *paddr  */ | 
|---|
| 187 |                   "mtc2   $0,     $24           \n"  /* PADDR_EXT <= 0   */    | 
|---|
| 188 |  | 
|---|
| 189 |                   "mtc2   $2,     $1            \n"  /* restore MMU_MODE */ | 
|---|
| 190 |                   : "=r" (value) | 
|---|
| 191 |                   : "r" (lsb), "r" (msb) | 
|---|
| 192 |                   : "$2", "$3" ); | 
|---|
| 193 |  | 
|---|
| 194 |     _it_restore(&sr); | 
|---|
| 195 |     return value; | 
|---|
| 196 | } | 
|---|
| 197 | //////////////////////////////////////////////// | 
|---|
| 198 | void _physical_write( unsigned long long paddr,  | 
|---|
| 199 |                       unsigned int       value )  | 
|---|
| 200 | { | 
|---|
| 201 |     unsigned int lsb = (unsigned int)paddr; | 
|---|
| 202 |     unsigned int msb = (unsigned int)(paddr >> 32); | 
|---|
| 203 |     unsigned int sr; | 
|---|
| 204 |  | 
|---|
| 205 |    _it_disable(&sr); | 
|---|
| 206 |  | 
|---|
| 207 |     asm volatile( "mfc2   $2,     $1           \n"  /* $2 <= MMU_MODE   */ | 
|---|
| 208 |                   "andi   $3,     $2,    0xb   \n" | 
|---|
| 209 |                   "mtc2   $3,     $1           \n"  /* DTLB off         */     | 
|---|
| 210 |  | 
|---|
| 211 |                   "mtc2   %2,     $24          \n"  /* PADDR_EXT <= msb */    | 
|---|
| 212 |                   "sw     %0,     0(%1)        \n"  /* *paddr <= value  */ | 
|---|
| 213 |                   "mtc2   $0,     $24          \n"  /* PADDR_EXT <= 0   */    | 
|---|
| 214 |  | 
|---|
| 215 |                   "mtc2   $2,     $1           \n"  /* restore MMU_MODE */ | 
|---|
| 216 |                   "sync                        \n" | 
|---|
| 217 |                   : | 
|---|
| 218 |                   : "r" (value), "r" (lsb), "r" (msb) | 
|---|
| 219 |                   : "$2", "$3" ); | 
|---|
| 220 |  | 
|---|
| 221 |     _it_restore(&sr); | 
|---|
| 222 | } | 
|---|
| 223 |  | 
|---|
| 224 | ///////////////////////////////////////////////////////////////// | 
|---|
| 225 | unsigned long long _physical_read_ull( unsigned long long paddr )  | 
|---|
| 226 | { | 
|---|
| 227 |     unsigned int data_lsb; | 
|---|
| 228 |     unsigned int data_msb; | 
|---|
| 229 |     unsigned int addr_lsb = (unsigned int) paddr; | 
|---|
| 230 |     unsigned int addr_msb = (unsigned int) (paddr >> 32); | 
|---|
| 231 |     unsigned int sr; | 
|---|
| 232 |  | 
|---|
| 233 |     _it_disable(&sr); | 
|---|
| 234 |  | 
|---|
| 235 |     asm volatile( "mfc2   $2,     $1           \n"  /* $2 <= MMU_MODE       */ | 
|---|
| 236 |                   "andi   $3,     $2,    0xb   \n" | 
|---|
| 237 |                   "mtc2   $3,     $1           \n"  /* DTLB off             */     | 
|---|
| 238 |  | 
|---|
| 239 |                   "mtc2   %3,     $24          \n"  /* PADDR_EXT <= msb     */    | 
|---|
| 240 |                   "lw     %0,     0(%2)        \n"  /* data_lsb <= *paddr   */ | 
|---|
| 241 |                   "lw     %1,     4(%2)        \n"  /* data_msb <= *paddr+4 */ | 
|---|
| 242 |                   "mtc2   $0,     $24          \n"  /* PADDR_EXT <= 0       */    | 
|---|
| 243 |  | 
|---|
| 244 |                   "mtc2   $2,     $1           \n"  /* restore MMU_MODE     */ | 
|---|
| 245 |                   : "=r" (data_lsb), "=r"(data_msb) | 
|---|
| 246 |                   : "r" (addr_lsb), "r" (addr_msb) | 
|---|
| 247 |                   : "$2", "$3" ); | 
|---|
| 248 |  | 
|---|
| 249 |     _it_restore(&sr); | 
|---|
| 250 |  | 
|---|
| 251 |     return ( (((unsigned long long)data_msb)<<32) + | 
|---|
| 252 |              (((unsigned long long)data_lsb)) ); | 
|---|
| 253 | } | 
|---|
| 254 |  | 
|---|
| 255 | /////////////////////////////////////////////////// | 
|---|
| 256 | void _physical_write_ull( unsigned long long paddr,  | 
|---|
| 257 |                           unsigned long long value )  | 
|---|
| 258 | { | 
|---|
| 259 |     unsigned int addr_lsb = (unsigned int)paddr; | 
|---|
| 260 |     unsigned int addr_msb = (unsigned int)(paddr >> 32); | 
|---|
| 261 |     unsigned int data_lsb = (unsigned int)value; | 
|---|
| 262 |     unsigned int data_msb = (unsigned int)(value >> 32); | 
|---|
| 263 |     unsigned int sr; | 
|---|
| 264 |  | 
|---|
| 265 |     _it_disable(&sr); | 
|---|
| 266 |  | 
|---|
| 267 |     asm volatile( "mfc2   $2,     $1           \n"  /* $2 <= MMU_MODE     */ | 
|---|
| 268 |                   "andi   $3,     $2,    0xb   \n" | 
|---|
| 269 |                   "mtc2   $3,     $1           \n"  /* DTLB off           */     | 
|---|
| 270 |  | 
|---|
| 271 |                   "mtc2   %3,     $24          \n"  /* PADDR_EXT <= msb   */    | 
|---|
| 272 |                   "sw     %0,     0(%2)        \n"  /* *paddr <= value    */ | 
|---|
| 273 |                   "sw     %1,     4(%2)        \n"  /* *paddr+4 <= value  */ | 
|---|
| 274 |                   "mtc2   $0,     $24          \n"  /* PADDR_EXT <= 0     */    | 
|---|
| 275 |  | 
|---|
| 276 |                   "mtc2   $2,     $1           \n"  /* restore MMU_MODE   */ | 
|---|
| 277 |                   "sync                        \n" | 
|---|
| 278 |                   : | 
|---|
| 279 |                   : "r"(data_lsb),"r"(data_msb),"r"(addr_lsb),"r"(addr_msb) | 
|---|
| 280 |                   : "$2", "$3" ); | 
|---|
| 281 |  | 
|---|
| 282 |     _it_restore(&sr); | 
|---|
| 283 | } | 
|---|
| 284 |  | 
|---|
| 285 | //////////////////////////////////////////////////// | 
|---|
| 286 | void _physical_memcpy( unsigned long long dst_paddr,  // dest buffer paddr | 
|---|
| 287 |                        unsigned long long src_paddr,  // source buffer paddr | 
|---|
| 288 |                        unsigned int size )            // bytes | 
|---|
| 289 | { | 
|---|
| 290 |     // check alignment constraints | 
|---|
| 291 |     if ( (dst_paddr & 3) || (src_paddr & 3) || (size & 3) )  | 
|---|
| 292 |     { | 
|---|
| 293 |         _puts("\n[GIET ERROR] in _physical_memcpy() : buffer unaligned\n"); | 
|---|
| 294 |         _exit(); | 
|---|
| 295 |     } | 
|---|
| 296 |  | 
|---|
| 297 |     unsigned int src_lsb = (unsigned int)src_paddr; | 
|---|
| 298 |     unsigned int src_msb = (unsigned int)(src_paddr >> 32); | 
|---|
| 299 |     unsigned int dst_lsb = (unsigned int)dst_paddr; | 
|---|
| 300 |     unsigned int dst_msb = (unsigned int)(dst_paddr >> 32); | 
|---|
| 301 |     unsigned int iter    = size>>2; | 
|---|
| 302 |     unsigned int data; | 
|---|
| 303 |     unsigned int sr; | 
|---|
| 304 |  | 
|---|
| 305 |     _it_disable(&sr); | 
|---|
| 306 |  | 
|---|
| 307 |     asm volatile( "mfc2   $2,     $1         \n" /* $2 <= current MMU_MODE */ | 
|---|
| 308 |                   "andi   $3,     $2,   0xb  \n" /* $3 <= new MMU_MODE     */ | 
|---|
| 309 |                   "mtc2   $3,     $1         \n" /* DTLB off               */     | 
|---|
| 310 |  | 
|---|
| 311 |                   "move   $4,     %5         \n" /* $4 < iter              */ | 
|---|
| 312 |                   "move   $5,     %1         \n" /* $5 < src_lsb           */ | 
|---|
| 313 |                   "move   $6,     %3         \n" /* $6 < src_lsb           */ | 
|---|
| 314 |  | 
|---|
| 315 |                   "ph_memcpy_loop:           \n" | 
|---|
| 316 |                   "mtc2   %2,     $24        \n" /* PADDR_EXT <= src_msb   */    | 
|---|
| 317 |                   "lw     %0,     0($5)      \n" /* data <= *src_paddr     */ | 
|---|
| 318 |                   "mtc2   %4,     $24        \n" /* PADDR_EXT <= dst_msb   */    | 
|---|
| 319 |                   "sw     %0,     0($6)      \n" /* *dst_paddr <= data     */ | 
|---|
| 320 |  | 
|---|
| 321 |                   "addi   $4,     $4,   -1   \n" /* iter = iter - 1        */ | 
|---|
| 322 |                   "addi   $5,     $5,   4    \n" /* src_lsb += 4           */ | 
|---|
| 323 |                   "addi   $6,     $6,   4    \n" /* dst_lsb += 4           */ | 
|---|
| 324 |                   "bne    $4,     $0, ph_memcpy_loop \n" | 
|---|
| 325 |                   "nop                       \n" | 
|---|
| 326 |  | 
|---|
| 327 |                   "mtc2   $0,     $24        \n" /* PADDR_EXT <= 0         */    | 
|---|
| 328 |                   "mtc2   $2,     $1         \n" /* restore MMU_MODE       */ | 
|---|
| 329 |                   : "=r" (data) | 
|---|
| 330 |                   : "r"(src_lsb),"r"(src_msb),"r"(dst_lsb), | 
|---|
| 331 |                     "r"(dst_msb), "r"(iter) | 
|---|
| 332 |                   : "$2", "$3", "$4", "$5", "$6" ); | 
|---|
| 333 |  | 
|---|
| 334 |     _it_restore(&sr); | 
|---|
| 335 | } // end _physical_memcpy() | 
|---|
| 336 |  | 
|---|
| 337 | //////////////////////////////////////////////// | 
|---|
| 338 | void _physical_memset( unsigned long long paddr,     // dest buffer paddr | 
|---|
| 339 |                        unsigned int       size,      // bytes | 
|---|
| 340 |                        unsigned int       data )     // written value | 
|---|
| 341 | { | 
|---|
| 342 |     // check alignment constraints | 
|---|
| 343 |     if ( (paddr & 3) || (size & 7) ) | 
|---|
| 344 |     { | 
|---|
| 345 |         _puts("\n[GIET ERROR] in _physical_memset() : buffer unaligned\n"); | 
|---|
| 346 |         _exit(); | 
|---|
| 347 |     } | 
|---|
| 348 |  | 
|---|
| 349 |     unsigned int lsb  = (unsigned int)paddr; | 
|---|
| 350 |     unsigned int msb  = (unsigned int)(paddr >> 32); | 
|---|
| 351 |     unsigned int sr; | 
|---|
| 352 |  | 
|---|
| 353 |     _it_disable(&sr); | 
|---|
| 354 |  | 
|---|
| 355 |     asm volatile( "mfc2   $8,     $1         \n" /* $8 <= current MMU_MODE */ | 
|---|
| 356 |                   "andi   $9,     $8,   0xb  \n" /* $9 <= new MMU_MODE     */ | 
|---|
| 357 |                   "mtc2   $9,     $1         \n" /* DTLB off               */ | 
|---|
| 358 |                   "mtc2   %3,     $24        \n" /* PADDR_EXT <= msb       */ | 
|---|
| 359 |  | 
|---|
| 360 |                   "1:                        \n" /* set 8 bytes per iter   */ | 
|---|
| 361 |                   "sw     %2,     0(%0)      \n" /* *src_paddr     = data  */ | 
|---|
| 362 |                   "sw     %2,     4(%0)      \n" /* *(src_paddr+4) = data  */ | 
|---|
| 363 |                   "addi   %1,     %1,   -8   \n" /* size -= 8              */ | 
|---|
| 364 |                   "addi   %0,     %0,    8   \n" /* src_paddr += 8         */ | 
|---|
| 365 |                   "bnez   %1,     1b         \n" /* loop while size != 0   */ | 
|---|
| 366 |  | 
|---|
| 367 |                   "mtc2   $0,     $24        \n" /* PADDR_EXT <= 0         */ | 
|---|
| 368 |                   "mtc2   $8,     $1         \n" /* restore MMU_MODE       */ | 
|---|
| 369 |                   : "+r"(lsb), "+r"(size) | 
|---|
| 370 |                   : "r"(data), "r" (msb) | 
|---|
| 371 |                   : "$8", "$9", "memory" ); | 
|---|
| 372 |  | 
|---|
| 373 |     _it_restore(&sr); | 
|---|
| 374 | }  // _physical_memset() | 
|---|
| 375 |  | 
|---|
| 376 | /////////////////////////////////////////////// | 
|---|
| 377 | void _io_extended_write( unsigned int*  vaddr, | 
|---|
| 378 |                          unsigned int   value ) | 
|---|
| 379 | { | 
|---|
| 380 |     unsigned long long paddr; | 
|---|
| 381 |  | 
|---|
| 382 |     if ( _get_mmu_mode() & 0x4 )  // MMU activated : use virtual address | 
|---|
| 383 |     { | 
|---|
| 384 |         *vaddr = value; | 
|---|
| 385 |     } | 
|---|
| 386 |     else                          // use paddr extension for IO | 
|---|
| 387 |     { | 
|---|
| 388 |         paddr = (unsigned long long)(unsigned int)vaddr + | 
|---|
| 389 |                 (((unsigned long long)((X_IO<<Y_WIDTH) + Y_IO))<<32);  | 
|---|
| 390 |         _physical_write( paddr, value ); | 
|---|
| 391 |     } | 
|---|
| 392 |     asm volatile("sync" ::: "memory"); | 
|---|
| 393 | } | 
|---|
| 394 |  | 
|---|
| 395 | ////////////////////////////////////////////////////// | 
|---|
| 396 | unsigned int _io_extended_read( unsigned int*  vaddr ) | 
|---|
| 397 | { | 
|---|
| 398 |     unsigned long long paddr; | 
|---|
| 399 |  | 
|---|
| 400 |     if ( _get_mmu_mode() & 0x4 )  // MMU activated : use virtual address | 
|---|
| 401 |     { | 
|---|
| 402 |         return *(volatile unsigned int*)vaddr; | 
|---|
| 403 |     } | 
|---|
| 404 |     else                          // use paddr extension for IO | 
|---|
| 405 |     { | 
|---|
| 406 |         paddr = (unsigned long long)(unsigned int)vaddr + | 
|---|
| 407 |                 (((unsigned long long)((X_IO<<Y_WIDTH) + Y_IO))<<32);  | 
|---|
| 408 |         return _physical_read( paddr ); | 
|---|
| 409 |     } | 
|---|
| 410 | } | 
|---|
| 411 |  | 
|---|
| 412 | //////////////////////////////////////////////////////////////////////////// | 
|---|
| 413 | //           Scheduler and tasks context access functions | 
|---|
| 414 | //////////////////////////////////////////////////////////////////////////// | 
|---|
| 415 |  | 
|---|
| 416 |  | 
|---|
| 417 | /////////////////////////////////// | 
|---|
| 418 | unsigned int _get_current_task_id()  | 
|---|
| 419 | { | 
|---|
| 420 |     static_scheduler_t * psched = (static_scheduler_t *) _get_sched(); | 
|---|
| 421 |     return (unsigned int) (psched->current); | 
|---|
| 422 | } | 
|---|
| 423 |  | 
|---|
| 424 | //////////////////////////////////////////// | 
|---|
| 425 | unsigned int _get_task_slot( unsigned int x, | 
|---|
| 426 |                              unsigned int y, | 
|---|
| 427 |                              unsigned int p, | 
|---|
| 428 |                              unsigned int ltid, | 
|---|
| 429 |                              unsigned int slot ) | 
|---|
| 430 | { | 
|---|
| 431 |     static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p]; | 
|---|
| 432 |     return psched->context[ltid][slot]; | 
|---|
| 433 | } | 
|---|
| 434 |  | 
|---|
| 435 | //////////////////////////////////// | 
|---|
| 436 | void _set_task_slot( unsigned int x, | 
|---|
| 437 |                      unsigned int y, | 
|---|
| 438 |                      unsigned int p, | 
|---|
| 439 |                      unsigned int ltid, | 
|---|
| 440 |                      unsigned int slot, | 
|---|
| 441 |                      unsigned int value ) | 
|---|
| 442 | { | 
|---|
| 443 |     static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p]; | 
|---|
| 444 |     psched->context[ltid][slot] = value; | 
|---|
| 445 | } | 
|---|
| 446 |  | 
|---|
| 447 | /////////////////////////////////////////////////// | 
|---|
| 448 | unsigned int _get_context_slot( unsigned int slot ) | 
|---|
| 449 | { | 
|---|
| 450 |     static_scheduler_t* psched  = (static_scheduler_t*)_get_sched(); | 
|---|
| 451 |     unsigned int        task_id = psched->current; | 
|---|
| 452 |     return psched->context[task_id][slot]; | 
|---|
| 453 | } | 
|---|
| 454 |  | 
|---|
| 455 | /////////////////////////////////////////// | 
|---|
| 456 | void _set_context_slot( unsigned int slot, | 
|---|
| 457 |                        unsigned int value ) | 
|---|
| 458 | { | 
|---|
| 459 |     static_scheduler_t* psched  = (static_scheduler_t*)_get_sched(); | 
|---|
| 460 |     unsigned int        task_id = psched->current; | 
|---|
| 461 |     psched->context[task_id][slot] = value; | 
|---|
| 462 | } | 
|---|
| 463 |  | 
|---|
| 464 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
| 465 | //      Access functions to mapping_info data structure | 
|---|
| 466 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
| 467 |  | 
|---|
| 468 | //////////////////////////////////////////////////////////////// | 
|---|
| 469 | mapping_cluster_t * _get_cluster_base(mapping_header_t * header)  | 
|---|
| 470 | { | 
|---|
| 471 |     return (mapping_cluster_t *) ((char *) header + | 
|---|
| 472 |             MAPPING_HEADER_SIZE); | 
|---|
| 473 | } | 
|---|
| 474 | ////////////////////////////////////////////////////////// | 
|---|
| 475 | mapping_pseg_t * _get_pseg_base(mapping_header_t * header)  | 
|---|
| 476 | { | 
|---|
| 477 |     return (mapping_pseg_t *) ((char *) header + | 
|---|
| 478 |             MAPPING_HEADER_SIZE + | 
|---|
| 479 |             MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE); | 
|---|
| 480 | } | 
|---|
| 481 | ////////////////////////////////////////////////////////////// | 
|---|
| 482 | mapping_vspace_t * _get_vspace_base(mapping_header_t * header)  | 
|---|
| 483 | { | 
|---|
| 484 |     return (mapping_vspace_t *)  ((char *) header + | 
|---|
| 485 |             MAPPING_HEADER_SIZE + | 
|---|
| 486 |             MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE + | 
|---|
| 487 |             MAPPING_PSEG_SIZE * header->psegs); | 
|---|
| 488 | } | 
|---|
| 489 | ////////////////////////////////////////////////////////// | 
|---|
| 490 | mapping_vseg_t * _get_vseg_base(mapping_header_t * header) | 
|---|
| 491 | { | 
|---|
| 492 |     return (mapping_vseg_t *) ((char *) header + | 
|---|
| 493 |             MAPPING_HEADER_SIZE + | 
|---|
| 494 |             MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE + | 
|---|
| 495 |             MAPPING_PSEG_SIZE * header->psegs + | 
|---|
| 496 |             MAPPING_VSPACE_SIZE * header->vspaces); | 
|---|
| 497 | } | 
|---|
| 498 | ////////////////////////////////////////////////////////// | 
|---|
| 499 | mapping_task_t * _get_task_base(mapping_header_t * header)  | 
|---|
| 500 | { | 
|---|
| 501 |     return (mapping_task_t *) ((char *) header + | 
|---|
| 502 |             MAPPING_HEADER_SIZE + | 
|---|
| 503 |             MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE + | 
|---|
| 504 |             MAPPING_PSEG_SIZE * header->psegs + | 
|---|
| 505 |             MAPPING_VSPACE_SIZE * header->vspaces + | 
|---|
| 506 |             MAPPING_VSEG_SIZE * header->vsegs); | 
|---|
| 507 | } | 
|---|
| 508 | ///////////////////////////////////////////////////////// | 
|---|
| 509 | mapping_proc_t *_get_proc_base(mapping_header_t * header)  | 
|---|
| 510 | { | 
|---|
| 511 |     return (mapping_proc_t *) ((char *) header + | 
|---|
| 512 |             MAPPING_HEADER_SIZE + | 
|---|
| 513 |             MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE + | 
|---|
| 514 |             MAPPING_PSEG_SIZE * header->psegs + | 
|---|
| 515 |             MAPPING_VSPACE_SIZE * header->vspaces + | 
|---|
| 516 |             MAPPING_VSEG_SIZE * header->vsegs + | 
|---|
| 517 |             MAPPING_TASK_SIZE * header->tasks); | 
|---|
| 518 | } | 
|---|
| 519 | /////////////////////////////////////////////////////// | 
|---|
| 520 | mapping_irq_t *_get_irq_base(mapping_header_t * header)  | 
|---|
| 521 | { | 
|---|
| 522 |     return (mapping_irq_t *) ((char *) header + | 
|---|
| 523 |             MAPPING_HEADER_SIZE + | 
|---|
| 524 |             MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE + | 
|---|
| 525 |             MAPPING_PSEG_SIZE * header->psegs + | 
|---|
| 526 |             MAPPING_VSPACE_SIZE * header->vspaces + | 
|---|
| 527 |             MAPPING_VSEG_SIZE * header->vsegs + | 
|---|
| 528 |             MAPPING_TASK_SIZE * header->tasks + | 
|---|
| 529 |             MAPPING_PROC_SIZE * header->procs); | 
|---|
| 530 | } | 
|---|
| 531 | /////////////////////////////////////////////////////////////// | 
|---|
| 532 | mapping_periph_t *_get_periph_base(mapping_header_t * header)  | 
|---|
| 533 | { | 
|---|
| 534 |     return (mapping_periph_t *) ((char *) header + | 
|---|
| 535 |             MAPPING_HEADER_SIZE + | 
|---|
| 536 |             MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE + | 
|---|
| 537 |             MAPPING_PSEG_SIZE * header->psegs + | 
|---|
| 538 |             MAPPING_VSPACE_SIZE * header->vspaces + | 
|---|
| 539 |             MAPPING_VSEG_SIZE * header->vsegs + | 
|---|
| 540 |             MAPPING_TASK_SIZE * header->tasks + | 
|---|
| 541 |             MAPPING_PROC_SIZE * header->procs + | 
|---|
| 542 |             MAPPING_IRQ_SIZE * header->irqs); | 
|---|
| 543 | } | 
|---|
| 544 |  | 
|---|
| 545 | /////////////////////////////////////////////////////////////////////////// | 
|---|
| 546 | //             Miscelaneous functions | 
|---|
| 547 | /////////////////////////////////////////////////////////////////////////// | 
|---|
| 548 |  | 
|---|
| 549 | ////////////////////////////////////// | 
|---|
| 550 | __attribute__((noreturn)) void _exit()  | 
|---|
| 551 | { | 
|---|
| 552 |     unsigned int procid = _get_procid(); | 
|---|
| 553 |     unsigned int x      = (procid >> (Y_WIDTH + P_WIDTH)) & ((1<<X_WIDTH)-1); | 
|---|
| 554 |     unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1); | 
|---|
| 555 |     unsigned int lpid   = procid & ((1<<P_WIDTH)-1); | 
|---|
| 556 |  | 
|---|
| 557 |  | 
|---|
| 558 |     _puts("\n[GIET PANIC] processor["); | 
|---|
| 559 |     _putd( x ); | 
|---|
| 560 |     _puts(","); | 
|---|
| 561 |     _putd( y ); | 
|---|
| 562 |     _puts(","); | 
|---|
| 563 |     _putd( lpid ); | 
|---|
| 564 |     _puts("] exit at cycle "); | 
|---|
| 565 |     _putd( _get_proctime() ); | 
|---|
| 566 |     _puts(" ...\n"); | 
|---|
| 567 |  | 
|---|
| 568 |     while (1) { asm volatile ("nop"); } | 
|---|
| 569 | } | 
|---|
| 570 |  | 
|---|
| 571 | ///////////////////////////////////// | 
|---|
| 572 | void _random_wait( unsigned int val ) | 
|---|
| 573 | { | 
|---|
| 574 |     unsigned int mask  = (1<<(val&0x1F))-1; | 
|---|
| 575 |     unsigned int delay = (_get_proctime() ^ (_get_procid()<<4)) & mask; | 
|---|
| 576 |     asm volatile( "move  $3,   %0                 \n" | 
|---|
| 577 |                   "loop_nic_completed:            \n" | 
|---|
| 578 |                   "nop                            \n" | 
|---|
| 579 |                   "addi  $3,   $3, -1             \n" | 
|---|
| 580 |                   "bnez  $3,   loop_nic_completed \n" | 
|---|
| 581 |                   "nop                            \n" | 
|---|
| 582 |                   : | 
|---|
| 583 |                   : "r" (delay) | 
|---|
| 584 |                   : "$3" );  | 
|---|
| 585 | } | 
|---|
| 586 |  | 
|---|
| 587 | /////////////////////////// | 
|---|
| 588 | void _break( char* string )  | 
|---|
| 589 | { | 
|---|
| 590 |     char byte; | 
|---|
| 591 |  | 
|---|
| 592 |     _puts("\n[GIET DEBUG] break from "); | 
|---|
| 593 |     _puts( string ); | 
|---|
| 594 |     _puts(" / stoke any key to continue\n"); | 
|---|
| 595 |     _getc( &byte ); | 
|---|
| 596 | } | 
|---|
| 597 |  | 
|---|
| 598 | /////////////////////////////////////// | 
|---|
| 599 | unsigned int _strncmp( const char * s1,  | 
|---|
| 600 |                        const char * s2,  | 
|---|
| 601 |                        unsigned int n )  | 
|---|
| 602 | { | 
|---|
| 603 |     unsigned int i; | 
|---|
| 604 |     for (i = 0; i < n; i++)  | 
|---|
| 605 |     { | 
|---|
| 606 |         if (s1[i] != s2[i])  return 1;  | 
|---|
| 607 |         if (s1[i] == 0)      break; | 
|---|
| 608 |     } | 
|---|
| 609 |     return 0; | 
|---|
| 610 | } | 
|---|
| 611 |  | 
|---|
| 612 | ///////////////////////////////////////// | 
|---|
| 613 | char* _strcpy( char* dest, char* source ) | 
|---|
| 614 | { | 
|---|
| 615 |     if (!dest || !source) return dest; | 
|---|
| 616 |  | 
|---|
| 617 |     while (*source) | 
|---|
| 618 |         *(dest++) = *(source++); | 
|---|
| 619 |  | 
|---|
| 620 |     return dest; | 
|---|
| 621 | } | 
|---|
| 622 |  | 
|---|
| 623 | ///////////////////////////////////////////////////// | 
|---|
| 624 | void _dcache_buf_invalidate( unsigned int buf_vbase,  | 
|---|
| 625 |                              unsigned int buf_size )  | 
|---|
| 626 | { | 
|---|
| 627 |     unsigned int offset; | 
|---|
| 628 |     unsigned int tmp; | 
|---|
| 629 |     unsigned int line_size;   // bytes | 
|---|
| 630 |  | 
|---|
| 631 |     // compute data cache line size based on config register (bits 12:10) | 
|---|
| 632 |     asm volatile( | 
|---|
| 633 |                  "mfc0 %0, $16, 1"  | 
|---|
| 634 |                  : "=r" (tmp) ); | 
|---|
| 635 |  | 
|---|
| 636 |     tmp = ((tmp >> 10) & 0x7); | 
|---|
| 637 |     line_size = 2 << tmp; | 
|---|
| 638 |  | 
|---|
| 639 |     // iterate on cache lines  | 
|---|
| 640 |     for ( offset = 0; offset < buf_size; offset += line_size)  | 
|---|
| 641 |     { | 
|---|
| 642 |         _set_mmu_dcache_inval( buf_vbase + offset ); | 
|---|
| 643 |     } | 
|---|
| 644 | } | 
|---|
| 645 |  | 
|---|
| 646 |  | 
|---|
| 647 |  | 
|---|
| 648 | ///////////////////////////////////////////// | 
|---|
| 649 | void _get_sqt_footprint( unsigned int* width, | 
|---|
| 650 |                          unsigned int* heigth, | 
|---|
| 651 |                          unsigned int* levels ) | 
|---|
| 652 | { | 
|---|
| 653 |     mapping_header_t*   header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE; | 
|---|
| 654 |     mapping_cluster_t*  cluster = _get_cluster_base(header); | 
|---|
| 655 |  | 
|---|
| 656 |     unsigned int x; | 
|---|
| 657 |     unsigned int y; | 
|---|
| 658 |     unsigned int cid; | 
|---|
| 659 |     unsigned int w = 0; | 
|---|
| 660 |     unsigned int h = 0; | 
|---|
| 661 |  | 
|---|
| 662 |     // scan all clusters to compute SQT footprint (w,h) | 
|---|
| 663 |     for ( x = 0 ; x < X_SIZE ; x++ ) | 
|---|
| 664 |     { | 
|---|
| 665 |         for ( y = 0 ; y < Y_SIZE ; y++ ) | 
|---|
| 666 |         { | 
|---|
| 667 |             cid = x * Y_SIZE + y; | 
|---|
| 668 |             if ( cluster[cid].procs )  // cluster contains processors | 
|---|
| 669 |             { | 
|---|
| 670 |                 if ( x > w ) w = x; | 
|---|
| 671 |                 if ( y > h ) h = y; | 
|---|
| 672 |             } | 
|---|
| 673 |         } | 
|---|
| 674 |     }            | 
|---|
| 675 |     *width  = w + 1; | 
|---|
| 676 |     *heigth = h + 1; | 
|---|
| 677 |      | 
|---|
| 678 |     // compute SQT levels | 
|---|
| 679 |     unsigned int z = (h > w) ? h : w; | 
|---|
| 680 |     *levels = (z < 1) ? 1 : (z < 2) ? 2 : (z < 4) ? 3 : (z < 8) ? 4 : 5; | 
|---|
| 681 | } | 
|---|
| 682 |       | 
|---|
| 683 |  | 
|---|
| 684 |  | 
|---|
| 685 | /////////////////////////////////////////////////////////////////////////// | 
|---|
| 686 | //   Required by GCC | 
|---|
| 687 | /////////////////////////////////////////////////////////////////////////// | 
|---|
| 688 |  | 
|---|
| 689 | //////////////////////////////// | 
|---|
| 690 | void* memcpy( void*        dest,     // dest buffer vbase | 
|---|
| 691 |               const void*  source,   // source buffer vbase | 
|---|
| 692 |               unsigned int size )    // bytes | 
|---|
| 693 | { | 
|---|
| 694 |     unsigned int* idst = (unsigned int*)dest; | 
|---|
| 695 |     unsigned int* isrc = (unsigned int*)source; | 
|---|
| 696 |  | 
|---|
| 697 |     // word-by-word copy | 
|---|
| 698 |     if (!((unsigned int) idst & 3) && !((unsigned int) isrc & 3))  | 
|---|
| 699 |     { | 
|---|
| 700 |         while (size > 3)  | 
|---|
| 701 |         { | 
|---|
| 702 |             *idst++ = *isrc++; | 
|---|
| 703 |             size -= 4; | 
|---|
| 704 |         } | 
|---|
| 705 |     } | 
|---|
| 706 |  | 
|---|
| 707 |     unsigned char* cdst = (unsigned char*)dest; | 
|---|
| 708 |     unsigned char* csrc = (unsigned char*)source; | 
|---|
| 709 |  | 
|---|
| 710 |     /* byte-by-byte copy */ | 
|---|
| 711 |     while (size--)  | 
|---|
| 712 |     { | 
|---|
| 713 |         *cdst++ = *csrc++; | 
|---|
| 714 |     } | 
|---|
| 715 |     return dest; | 
|---|
| 716 | } | 
|---|
| 717 |  | 
|---|
| 718 | ///////////////////////////////// | 
|---|
| 719 | void * memset( void*        dst,  | 
|---|
| 720 |                int          value,  | 
|---|
| 721 |                unsigned int count )  | 
|---|
| 722 | { | 
|---|
| 723 |     // word-by-word copy | 
|---|
| 724 |     unsigned int* idst = dst; | 
|---|
| 725 |     unsigned int  data = (((unsigned char)value)      ) | | 
|---|
| 726 |                          (((unsigned char)value) <<  8) | | 
|---|
| 727 |                          (((unsigned char)value) << 16) | | 
|---|
| 728 |                          (((unsigned char)value) << 24) ; | 
|---|
| 729 |  | 
|---|
| 730 |     if ( ! ((unsigned int)idst & 3) ) | 
|---|
| 731 |     { | 
|---|
| 732 |         while ( count > 3 ) | 
|---|
| 733 |         { | 
|---|
| 734 |             *idst++ = data; | 
|---|
| 735 |             count -= 4; | 
|---|
| 736 |         } | 
|---|
| 737 |     } | 
|---|
| 738 |     | 
|---|
| 739 |     // byte-by-byte copy | 
|---|
| 740 |     unsigned char* cdst = dst; | 
|---|
| 741 |     while (count--)  | 
|---|
| 742 |     { | 
|---|
| 743 |         *cdst++ = (unsigned char)value; | 
|---|
| 744 |     } | 
|---|
| 745 |     return dst; | 
|---|
| 746 | } | 
|---|
| 747 |  | 
|---|
| 748 |  | 
|---|
| 749 | // Local Variables: | 
|---|
| 750 | // tab-width: 4 | 
|---|
| 751 | // c-basic-offset: 4 | 
|---|
| 752 | // c-file-offsets:((innamespace . 0)(inline-open . 0)) | 
|---|
| 753 | // indent-tabs-mode: nil | 
|---|
| 754 | // End: | 
|---|
| 755 | // vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4 | 
|---|
| 756 |  | 
|---|