source: soft/giet_vm/giet_common/utils.c @ 444

Last change on this file since 444 was 442, checked in by alain, 10 years ago

Removing the _printf() function in the boot code i
and in the drivers used by the boot code.

File size: 30.6 KB
RevLine 
[258]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// They define more or less the GIET-VM HAL (Hardware Abstraction Layer),
9// and contains various utility functions, that can be used by both the
10// boot code and the kernel code.
11///////////////////////////////////////////////////////////////////////////////////
12
[442]13#include <utils.h>
[258]14#include <giet_config.h>
[324]15#include <hard_config.h>
[258]16#include <mapping_info.h>
[442]17#include <tty_driver.h>
[258]18#include <ctx_handler.h>
19
20// This global variable is allocated in the boot.c file or in kernel_init.c file
[430]21extern static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX];
[258]22
23///////////////////////////////////////////////////////////////////////////////////
[399]24//         CP0 registers access functions
[258]25///////////////////////////////////////////////////////////////////////////////////
26
[408]27/////////////////////////
[378]28unsigned int _get_sched() 
[258]29{
30    unsigned int ret;
[295]31    asm volatile( "mfc0      %0,     $4,2    \n" 
32                  : "=r"(ret) );
[258]33    return ret;
34}
[408]35///////////////////////
[378]36unsigned int _get_epc() 
[258]37{
38    unsigned int ret;
[295]39    asm volatile( "mfc0      %0,    $14     \n"
40                  : "=r"(ret) );
[258]41    return ret;
42}
[408]43////////////////////////
[378]44unsigned int _get_bvar() 
[258]45{
46    unsigned int ret;
[295]47    asm volatile( "mfc0      %0,    $8     \n"
48                  : "=r"(ret));
[258]49    return ret;
50}
[408]51//////////////////////
[378]52unsigned int _get_cr() 
[258]53{
54    unsigned int ret;
[295]55    asm volatile( "mfc0      %0,    $13    \n"
56                  : "=r"(ret));
[258]57    return ret;
58}
[408]59//////////////////////
[378]60unsigned int _get_sr() 
[258]61{
62    unsigned int ret;
[295]63    asm volatile( "mfc0      %0,     $12   \n"
64                  : "=r"(ret));
[258]65    return ret;
66}
[408]67//////////////////////////
[378]68unsigned int _get_procid() 
[258]69{
70    unsigned int ret;
[295]71    asm volatile ( "mfc0     %0,     $15, 1  \n"
72                   :"=r" (ret) );
[430]73    return (ret & 0xFFF);
[258]74}
[408]75////////////////////////////
[378]76unsigned int _get_proctime() 
[258]77{
78    unsigned int ret;
[295]79    asm volatile ( "mfc0     %0,     $9      \n"
80                   :"=r" (ret) );
[258]81    return ret;
82}
[408]83
84/////////////////////////////////////////////
[378]85void _it_disable( unsigned int * save_sr_ptr) 
[258]86{
[345]87    unsigned int sr = 0;
[295]88    asm volatile( "li      $3,        0xFFFFFFFE    \n"
89                  "mfc0    %0,        $12           \n"
90                  "and     $3,        $3,   %0      \n" 
91                  "mtc0    $3,        $12           \n" 
[345]92                  : "+r"(sr)
[295]93                  :
[345]94                  : "$3" );
[295]95    *save_sr_ptr = sr;
[258]96}
[408]97//////////////////////////////////////////////
[378]98void _it_restore( unsigned int * save_sr_ptr ) 
[295]99{
100    unsigned int sr = *save_sr_ptr;
101    asm volatile( "mtc0    %0,        $12           \n" 
102                  :
[301]103                  : "r"(sr)
104                  : "memory" );
[295]105}
106
[408]107/////////////////////////////////
[399]108void _set_sched(unsigned int val) 
109{
110    asm volatile ( "mtc0     %0,     $4, 2          \n"
111                   :
112                   :"r" (val) );
113}
[408]114//////////////////////////////
115void _set_sr(unsigned int val) 
116{
117    asm volatile ( "mtc0     %0,     $12            \n"
118                   :
119                   :"r" (val) );
120}
[399]121
[408]122
[399]123///////////////////////////////////////////////////////////////////////////////////
124//         CP2 registers access functions
125///////////////////////////////////////////////////////////////////////////////////
126
[408]127////////////////////////////
[399]128unsigned int _get_mmu_ptpr() 
129{
130    unsigned int ret;
131    asm volatile( "mfc2      %0,     $0      \n"
132                  : "=r"(ret) );
133    return ret;
134}
[408]135////////////////////////////
[399]136unsigned int _get_mmu_mode() 
137{
138    unsigned int ret;
139    asm volatile( "mfc2      %0,     $1      \n"
140                  : "=r"(ret) );
141    return ret;
142}
[408]143////////////////////////////////////
[378]144void _set_mmu_ptpr(unsigned int val) 
[258]145{
[408]146    asm volatile ( "mtc2     %0,     $0      \n"
[295]147                   :
[345]148                   :"r" (val)
149                   :"memory" );
[258]150}
[408]151////////////////////////////////////
[378]152void _set_mmu_mode(unsigned int val) 
[258]153{
[408]154    asm volatile ( "mtc2     %0,     $1      \n"
[295]155                   :
[345]156                   :"r" (val)
157                   :"memory" );
[258]158}
[408]159////////////////////////////////////////////
160void _set_mmu_dcache_inval(unsigned int val) 
161{
162    asm volatile ( "mtc2     %0,     $7      \n"
163                   :
164                   :"r" (val)
165                   :"memory" );
166}
[258]167
[408]168
[258]169////////////////////////////////////////////////////////////////////////////
170//          Physical addressing related functions
171////////////////////////////////////////////////////////////////////////////
172
[442]173///////////////////////////////////////////////////////
[378]174unsigned int _physical_read( unsigned long long paddr ) 
[258]175{
176    unsigned int value;
177    unsigned int lsb = (unsigned int) paddr;
178    unsigned int msb = (unsigned int) (paddr >> 32);
[301]179    unsigned int sr;
[258]180
[301]181    _it_disable(&sr);
[258]182
[344]183    asm volatile( "mfc2   $2,     $1                 \n"     /* $2 <= MMU_MODE   */
184                  "andi   $3,     $2,        0xb     \n"
185                  "mtc2   $3,     $1                 \n"     /* DTLB off         */   
[258]186
[344]187                  "mtc2   %2,     $24                \n"     /* PADDR_EXT <= msb */   
188                  "lw     %0,     0(%1)              \n"     /* value <= *paddr  */
189                  "mtc2   $0,     $24                \n"     /* PADDR_EXT <= 0   */   
190
191                  "mtc2   $2,     $1                 \n"     /* restore MMU_MODE */
192                  : "=r" (value)
193                  : "r" (lsb), "r" (msb)
194                  : "$2", "$3" );
195
[301]196    _it_restore(&sr);
[258]197    return value;
198}
[442]199////////////////////////////////////////////////
[378]200void _physical_write( unsigned long long paddr, 
[430]201                      unsigned int       value ) 
[258]202{
203    unsigned int lsb = (unsigned int)paddr;
204    unsigned int msb = (unsigned int)(paddr >> 32);
[301]205    unsigned int sr;
[258]206
[430]207   _it_disable(&sr);
[258]208
[344]209    asm volatile( "mfc2   $2,     $1                 \n"     /* $2 <= MMU_MODE   */
210                  "andi   $3,     $2,        0xb     \n"
211                  "mtc2   $3,     $1                 \n"     /* DTLB off         */   
[258]212
[344]213                  "mtc2   %2,     $24                \n"     /* PADDR_EXT <= msb */   
214                  "sw     %0,     0(%1)              \n"     /* *paddr <= value  */
215                  "mtc2   $0,     $24                \n"     /* PADDR_EXT <= 0   */   
216
217                  "mtc2   $2,     $1                 \n"     /* restore MMU_MODE */
[345]218                  "sync                              \n"
[344]219                  :
220                  : "r" (value), "r" (lsb), "r" (msb)
221                  : "$2", "$3" );
222
[301]223    _it_restore(&sr);
[258]224}
225
[442]226/////////////////////////////////////////////////////////////////
[378]227unsigned long long _physical_read_ull( unsigned long long paddr ) 
[370]228{
229    unsigned int data_lsb;
230    unsigned int data_msb;
231    unsigned int addr_lsb = (unsigned int) paddr;
232    unsigned int addr_msb = (unsigned int) (paddr >> 32);
233    unsigned int sr;
234
235    _it_disable(&sr);
236
237    asm volatile( "mfc2   $2,     $1                 \n"     /* $2 <= MMU_MODE       */
238                  "andi   $3,     $2,        0xb     \n"
239                  "mtc2   $3,     $1                 \n"     /* DTLB off             */   
240
241                  "mtc2   %3,     $24                \n"     /* PADDR_EXT <= msb     */   
242                  "lw     %0,     0(%2)              \n"     /* data_lsb <= *paddr   */
243                  "lw     %1,     4(%2)              \n"     /* data_msb <= *paddr+4 */
244                  "mtc2   $0,     $24                \n"     /* PADDR_EXT <= 0       */   
245
246                  "mtc2   $2,     $1                 \n"     /* restore MMU_MODE     */
247                  : "=r" (data_lsb), "=r"(data_msb)
248                  : "r" (addr_lsb), "r" (addr_msb)
249                  : "$2", "$3" );
250
251    _it_restore(&sr);
252
253    return ( (((unsigned long long)data_msb)<<32) +
254             (((unsigned long long)data_lsb)) );
255}
256
[442]257///////////////////////////////////////////////////
[378]258void _physical_write_ull( unsigned long long paddr, 
[399]259                          unsigned long long value ) 
[370]260{
261    unsigned int addr_lsb = (unsigned int)paddr;
262    unsigned int addr_msb = (unsigned int)(paddr >> 32);
263    unsigned int data_lsb = (unsigned int)value;
264    unsigned int data_msb = (unsigned int)(value >> 32);
265    unsigned int sr;
266
267    _it_disable(&sr);
268
269    asm volatile( "mfc2   $2,     $1                 \n"     /* $2 <= MMU_MODE     */
270                  "andi   $3,     $2,        0xb     \n"
271                  "mtc2   $3,     $1                 \n"     /* DTLB off           */   
272
273                  "mtc2   %3,     $24                \n"     /* PADDR_EXT <= msb   */   
274                  "sw     %0,     0(%2)              \n"     /* *paddr <= value    */
275                  "sw     %1,     4(%2)              \n"     /* *paddr+4 <= value  */
276                  "mtc2   $0,     $24                \n"     /* PADDR_EXT <= 0     */   
277
278                  "mtc2   $2,     $1                 \n"     /* restore MMU_MODE   */
279                  "sync                              \n"
280                  :
281                  : "r" (data_lsb), "r" (data_msb), "r" (addr_lsb), "r" (addr_msb)
282                  : "$2", "$3" );
283
284    _it_restore(&sr);
285}
286
[442]287////////////////////////////////////////////////////
[430]288void _physical_memcpy( unsigned long long dst_paddr,  // destination buffer paddr
[399]289                       unsigned long long src_paddr,  // source buffer paddr
290                       unsigned int size )            // bytes
[344]291{
292    // check alignment constraints
293    if ( (dst_paddr & 3) || (src_paddr & 3) || (size & 3) ) 
294    {
[442]295        _puts("\n[GIET ERROR] in _physical_memcpy() : buffer unaligned\n");
[344]296        _exit();
297    }
298
299    unsigned int src_lsb = (unsigned int)src_paddr;
300    unsigned int src_msb = (unsigned int)(src_paddr >> 32);
301    unsigned int dst_lsb = (unsigned int)dst_paddr;
302    unsigned int dst_msb = (unsigned int)(dst_paddr >> 32);
303    unsigned int iter    = size>>2;
304    unsigned int data;
305    unsigned int sr;
306
307    _it_disable(&sr);
308
309    asm volatile( "mfc2   $2,     $1                 \n"     /* $2 <= current MMU_MODE */
310                  "andi   $3,     $2,        0xb     \n"     /* $3 <= new MMU_MODE     */
311                  "mtc2   $3,     $1                 \n"     /* DTLB off               */   
312
313                  "move   $4,     %5                 \n"     /* $4 < iter              */
314                  "move   $5,     %1                 \n"     /* $5 < src_lsb           */
315                  "move   $6,     %3                 \n"     /* $6 < src_lsb           */
316
317                  "ph_memcpy_loop:                   \n"
318                  "mtc2   %2,     $24                \n"     /* PADDR_EXT <= src_msb   */   
319                  "lw     %0,     0($5)              \n"     /* data <= *src_paddr     */
320                  "mtc2   %4,     $24                \n"     /* PADDR_EXT <= dst_msb   */   
321                  "sw     %0,     0($6)              \n"     /* *dst_paddr <= data     */
322
323                  "addi   $4,     $4,       -1       \n"     /* iter = iter - 1        */
324                  "addi   $5,     $5,        4       \n"     /* src_lsb += 4           */
325                  "addi   $6,     $6,        4       \n"     /* dst_lsb += 4           */
326                  "bne    $4,     $0, ph_memcpy_loop \n"
327                  "nop                               \n"
328
329                  "mtc2   $0,     $24                \n"     /* PADDR_EXT <= 0         */   
330                  "mtc2   $2,     $1                 \n"     /* restore MMU_MODE       */
331                  : "=r" (data)
332                  : "r" (src_lsb), "r" (src_msb), "r" (dst_lsb), "r"(dst_msb), "r"(iter)
333                  : "$2", "$3", "$4", "$5", "$6" );
334
335    _it_restore(&sr);
[430]336} // end _physical_memcpy()
[344]337
[442]338////////////////////////////////////////////////
[430]339void _physical_memset( unsigned long long paddr,     // destination buffer paddr
340                       unsigned int       size,      // bytes
341                       unsigned int       data )     // written value
342{
343    // check alignment constraints
[433]344    if ( (paddr & 3) || (size & 7) )
[430]345    {
[442]346        _puts("\n[GIET ERROR] in _physical_memset() : buffer unaligned\n");
[430]347        _exit();
348    }
349
350    unsigned int lsb  = (unsigned int)paddr;
351    unsigned int msb  = (unsigned int)(paddr >> 32);
352    unsigned int sr;
353
354    _it_disable(&sr);
355
[433]356    asm volatile( "mfc2   $8,     $1                 \n"     /* $8 <= current MMU_MODE */
357                  "andi   $9,     $8,        0xb     \n"     /* $9 <= new MMU_MODE     */
358                  "mtc2   $9,     $1                 \n"     /* DTLB off               */
359                  "mtc2   %3,     $24                \n"     /* PADDR_EXT <= msb       */
[430]360
[433]361                  "1:                                \n"     /* set 8 bytes per iter   */
362                  "sw     %2,     0(%0)              \n"     /* *src_paddr     = data  */
363                  "sw     %2,     4(%0)              \n"     /* *(src_paddr+4) = data  */
364                  "addi   %1,     %1,       -8       \n"     /* size -= 8              */
365                  "addi   %0,     %0,        8       \n"     /* src_paddr += 8         */
366                  "bnez   %1,     1b                 \n"     /* loop while size != 0   */
[430]367
[433]368                  "mtc2   $0,     $24                \n"     /* PADDR_EXT <= 0         */
369                  "mtc2   $8,     $1                 \n"     /* restore MMU_MODE       */
370                  : "+r"(lsb), "+r"(size)
371                  : "r"(data), "r" (msb)
372                  : "$8", "$9", "memory" );
[430]373
374    _it_restore(&sr);
[433]375}  // _physical_memset()
[430]376
[442]377///////////////////////////////////////////////
[378]378void _io_extended_write( unsigned int*  vaddr,
[399]379                         unsigned int   value )
[295]380{
381    unsigned long long paddr;
382
383    if ( _get_mmu_mode() & 0x4 )  // MMU activated : use virtual address
384    {
385        *vaddr = value;
386    }
387    else                          // use paddr extension for IO
388    {
389        paddr = (unsigned long long)(unsigned int)vaddr +
390                (((unsigned long long)((X_IO<<Y_WIDTH) + Y_IO))<<32); 
391        _physical_write( paddr, value );
392    }
393    asm volatile("sync" ::: "memory");
394}
395
[442]396//////////////////////////////////////////////////////
[378]397unsigned int _io_extended_read( unsigned int*  vaddr )
[295]398{
399    unsigned long long paddr;
400
401    if ( _get_mmu_mode() & 0x4 )  // MMU activated : use virtual address
402    {
403        return *(volatile unsigned int*)vaddr;
404    }
405    else                          // use paddr extension for IO
406    {
407        paddr = (unsigned long long)(unsigned int)vaddr +
408                (((unsigned long long)((X_IO<<Y_WIDTH) + Y_IO))<<32); 
409        return _physical_read( paddr );
410    }
411}
412
413///////////////////////////////////////////////////////////////////////////////////
[442]414//                      Locks access functions
[258]415///////////////////////////////////////////////////////////////////////////////////
416
[442]417///////////////////////////////////
418void _get_lock( giet_lock_t* lock ) 
[258]419{
[351]420    register unsigned int* plock = &(lock->value);
421
[314]422#if NO_HARD_CC
423
[351]424    register unsigned int delay  = (_get_proctime() ^ _get_procid() << 4) & 0xFF;
425    if (delay == 0) delay = 0x80;
[258]426
427    asm volatile (
428            "_lock_llsc:             \n"
[351]429            "    ll   $2,    0(%0)       \n" /* $2 <= lock current value         */
430            "    bnez $2,    _lock_delay \n" /* delay if lock already taken      */
431            "    li   $3,    1           \n" /* $3 <= argument for sc            */
432            "    sc   $3,    0(%0)       \n" /* try to set lock                  */
433            "    bnez $3,    _lock_ok    \n" /* exit if atomic                   */
434            "    _lock_delay:            \n"
435            "    move $4,    %1          \n" /* $4 <= delay                      */
436            "    _lock_loop:             \n"
437            "    addi $4,    $4,    -1   \n" /* $4 <= $4 - 1                     */
438            "    bnez $4,    _lock_loop  \n" /* test end delay                   */
439            "    nop                     \n"
440            "    j           _lock_llsc  \n" /* retry                            */
441            "    nop                     \n"
442            "    _lock_ok:               \n"
[258]443            :
444            :"r"(plock), "r"(delay)
[345]445            :"$2", "$3", "$4", "memory");
[314]446#else
447
448    asm volatile (
449            "_lock_llsc:                 \n"
[351]450            "    lw   $2,    0(%0)       \n" /* $2 <= lock current value         */
451            "    bnez $2,    _lock_llsc  \n" /* retry if lock already taken      */
[314]452            "    nop                     \n"
[351]453            "    ll   $2,    0(%0)       \n" /* ll_buffer <= lock current value  */
454            "    bnez $2,    _lock_llsc  \n" /* retry if lock already taken      */
455            "    li   $3,    1           \n" /* $3 <= argument for sc            */
456            "    sc   $3,    0(%0)       \n" /* try to set lock                  */
457            "    beqz $3,    _lock_llsc  \n" /* retry if sc failure              */
[314]458            "    nop                     \n"
459            :
460            :"r"(plock)
[345]461            :"$2", "$3", "memory");
[314]462#endif
463
[258]464}
[295]465
[442]466///////////////////////////////////////
467void _release_lock( giet_lock_t* lock ) 
[258]468{
[295]469    asm volatile ( "sync\n" ::: "memory" ); 
470    // sync is necessary because of the TSAR consistency model
[351]471    lock->value = 0;
[258]472}
473
474///////////////////////////////////////////////////////////////////////////////////
[442]475//           Access functions to kernel terminal TTY0
[258]476///////////////////////////////////////////////////////////////////////////////////
[295]477
[442]478//////////////////////////
[295]479void _puts( char* string ) 
[258]480{
[295]481    unsigned int n = 0;
482
483    while ( string[n] > 0 )
[258]484    {
[295]485        // test status register
486        while ( (_tty_get_register( 0, TTY_STATUS ) & 0x2) );
487
488        // write one byte
[315]489        if ( string[n] == '\n') {
490            _tty_set_register( 0, TTY_WRITE, (unsigned int)'\r' );
491        }
[295]492        _tty_set_register( 0, TTY_WRITE, (unsigned int)string[n] );
493        n++;
[258]494    }
495}
496
[442]497//////////////////////////////
[295]498void _putx( unsigned int val )
[258]499{
500    static const char HexaTab[] = "0123456789ABCDEF";
501    char buf[11];
502    unsigned int c;
503
504    buf[0] = '0';
505    buf[1] = 'x';
506    buf[10] = 0;
507
508    for (c = 0; c < 8; c++) 
509    { 
510        buf[9 - c] = HexaTab[val & 0xF];
511        val = val >> 4;
512    }
[295]513    _puts( buf );
[258]514}
515
[442]516////////////////////////////////////
[295]517void _putl( unsigned long long val )
[258]518{
519    static const char HexaTab[] = "0123456789ABCDEF";
520    char buf[19];
521    unsigned int c;
522
523    buf[0] = '0';
524    buf[1] = 'x';
525    buf[18] = 0;
526
527    for (c = 0; c < 16; c++) 
528    { 
529        buf[17 - c] = HexaTab[(unsigned int)val & 0xF];
530        val = val >> 4;
531    }
[295]532    _puts( buf );
[258]533}
534
[442]535//////////////////////////////
[295]536void _putd( unsigned int val ) 
[258]537{
538    static const char DecTab[] = "0123456789";
539    char buf[11];
540    unsigned int i;
[351]541    unsigned int first = 0;
[258]542
543    buf[10] = 0;
544
[351]545    for (i = 0; i < 10; i++) 
546    {
547        if ((val != 0) || (i == 0)) 
548        {
[258]549            buf[9 - i] = DecTab[val % 10];
550            first = 9 - i;
551        }
[351]552        else 
553        {
[258]554            break;
555        }
556        val /= 10;
557    }
[295]558    _puts( &buf[first] );
[258]559}
560
[442]561/////////////////////////
562void _getc( char*  byte )
[295]563{
564    // test status register
565    while ( _tty_get_register( 0, TTY_STATUS ) == 0 );
566
567    // read one byte
568    *byte = (char)_tty_get_register( 0, TTY_READ );
569}
570
[258]571
[430]572////////////////////////////////////////////////////////////////////////////////////
[399]573//           Scheduler and tasks context access functions
[430]574////////////////////////////////////////////////////////////////////////////////////
[258]575
[430]576
[442]577///////////////////////////////////
[399]578unsigned int _get_current_task_id() 
[258]579{
[399]580    static_scheduler_t * psched = (static_scheduler_t *) _get_sched();
581    return (unsigned int) (psched->current);
[258]582}
[442]583
584////////////////////////////////////////////
[430]585unsigned int _get_task_slot( unsigned int x,
586                             unsigned int y,
587                             unsigned int p,
[258]588                             unsigned int ltid,
589                             unsigned int slot )
590{
[430]591    static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p];
[258]592    return psched->context[ltid][slot];
593}
[442]594
595////////////////////////////////////
[430]596void _set_task_slot( unsigned int x,
597                     unsigned int y,
598                     unsigned int p,
[258]599                     unsigned int ltid,
600                     unsigned int slot,
601                     unsigned int value )
602{
[430]603    static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p];
[258]604    psched->context[ltid][slot] = value;
605}
[442]606
607///////////////////////////////////////////////////
[258]608unsigned int _get_context_slot( unsigned int slot )
609{
610    static_scheduler_t* psched  = (static_scheduler_t*)_get_sched();
611    unsigned int        task_id = psched->current;
612    return psched->context[task_id][slot];
613}
[442]614
615///////////////////////////////////////////
[258]616void _set_context_slot( unsigned int slot,
617                       unsigned int value )
618{
619    static_scheduler_t* psched  = (static_scheduler_t*)_get_sched();
620    unsigned int        task_id = psched->current;
621    psched->context[task_id][slot] = value;
622}
623
624/////////////////////////////////////////////////////////////////////////////
625//      Access functions to mapping_info data structure
626/////////////////////////////////////////////////////////////////////////////
[442]627
628////////////////////////////////////////////////////////////////
[378]629mapping_cluster_t * _get_cluster_base(mapping_header_t * header) 
[258]630{
631    return (mapping_cluster_t *) ((char *) header +
632            MAPPING_HEADER_SIZE);
633}
[442]634//////////////////////////////////////////////////////////
[378]635mapping_pseg_t * _get_pseg_base(mapping_header_t * header) 
[258]636{
637    return (mapping_pseg_t *) ((char *) header +
638            MAPPING_HEADER_SIZE +
[263]639            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE);
[258]640}
[442]641//////////////////////////////////////////////////////////////
[378]642mapping_vspace_t * _get_vspace_base(mapping_header_t * header) 
[258]643{
644    return (mapping_vspace_t *)  ((char *) header +
645            MAPPING_HEADER_SIZE +
[263]646            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
[258]647            MAPPING_PSEG_SIZE * header->psegs);
648}
[442]649//////////////////////////////////////////////////////////
[378]650mapping_vseg_t * _get_vseg_base(mapping_header_t * header)
[258]651{
652    return (mapping_vseg_t *) ((char *) header +
653            MAPPING_HEADER_SIZE +
[263]654            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
[258]655            MAPPING_PSEG_SIZE * header->psegs +
656            MAPPING_VSPACE_SIZE * header->vspaces);
657}
[442]658//////////////////////////////////////////////////////////
[378]659mapping_vobj_t * _get_vobj_base(mapping_header_t * header) 
[258]660{
661    return (mapping_vobj_t *) ((char *) header +
662            MAPPING_HEADER_SIZE +
[263]663            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
[258]664            MAPPING_PSEG_SIZE * header->psegs +
665            MAPPING_VSPACE_SIZE * header->vspaces +
666            MAPPING_VSEG_SIZE * header->vsegs );
667}
[442]668//////////////////////////////////////////////////////////
[378]669mapping_task_t * _get_task_base(mapping_header_t * header) 
[258]670{
671    return (mapping_task_t *) ((char *) header +
672            MAPPING_HEADER_SIZE +
[263]673            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
[258]674            MAPPING_PSEG_SIZE * header->psegs +
675            MAPPING_VSPACE_SIZE * header->vspaces +
676            MAPPING_VOBJ_SIZE * header->vobjs +
677            MAPPING_VSEG_SIZE * header->vsegs);
678}
[442]679/////////////////////////////////////////////////////////
[378]680mapping_proc_t *_get_proc_base(mapping_header_t * header) 
[258]681{
682    return (mapping_proc_t *) ((char *) header +
683            MAPPING_HEADER_SIZE +
[263]684            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
[258]685            MAPPING_PSEG_SIZE * header->psegs +
686            MAPPING_VSPACE_SIZE * header->vspaces +
687            MAPPING_VSEG_SIZE * header->vsegs +
688            MAPPING_VOBJ_SIZE * header->vobjs +
689            MAPPING_TASK_SIZE * header->tasks);
690}
[442]691///////////////////////////////////////////////////////
[378]692mapping_irq_t *_get_irq_base(mapping_header_t * header) 
[258]693{
694    return (mapping_irq_t *) ((char *) header +
695            MAPPING_HEADER_SIZE +
[263]696            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
[258]697            MAPPING_PSEG_SIZE * header->psegs +
698            MAPPING_VSPACE_SIZE * header->vspaces +
699            MAPPING_VSEG_SIZE * header->vsegs +
700            MAPPING_VOBJ_SIZE * header->vobjs +
701            MAPPING_TASK_SIZE * header->tasks +
702            MAPPING_PROC_SIZE * header->procs);
703}
[442]704/////////////////////////////////////////////////////////////
[378]705mapping_coproc_t *_get_coproc_base(mapping_header_t * header) 
[258]706{
707    return (mapping_coproc_t *) ((char *) header +
708            MAPPING_HEADER_SIZE +
[263]709            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
[258]710            MAPPING_PSEG_SIZE * header->psegs +
711            MAPPING_VSPACE_SIZE * header->vspaces +
712            MAPPING_VOBJ_SIZE * header->vobjs +
713            MAPPING_VSEG_SIZE * header->vsegs +
714            MAPPING_TASK_SIZE * header->tasks +
715            MAPPING_PROC_SIZE * header->procs +
716            MAPPING_IRQ_SIZE * header->irqs);
717}
[442]718///////////////////////////////////////////////////////////////
[378]719mapping_cp_port_t *_get_cp_port_base(mapping_header_t * header) 
[258]720{
721    return (mapping_cp_port_t *) ((char *) header +
722            MAPPING_HEADER_SIZE +
[263]723            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
[258]724            MAPPING_PSEG_SIZE * header->psegs +
725            MAPPING_VSPACE_SIZE * header->vspaces +
726            MAPPING_VOBJ_SIZE * header->vobjs +
727            MAPPING_VSEG_SIZE * header->vsegs +
728            MAPPING_TASK_SIZE * header->tasks +
729            MAPPING_PROC_SIZE * header->procs +
730            MAPPING_IRQ_SIZE * header->irqs +
731            MAPPING_COPROC_SIZE * header->coprocs);
732}
[442]733/////////////////////////////////////////////////////////////
[378]734mapping_periph_t *_get_periph_base(mapping_header_t * header) 
[258]735{
736    return (mapping_periph_t *) ((char *) header +
737            MAPPING_HEADER_SIZE +
[263]738            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
[258]739            MAPPING_PSEG_SIZE * header->psegs +
740            MAPPING_VSPACE_SIZE * header->vspaces +
741            MAPPING_VOBJ_SIZE * header->vobjs +
742            MAPPING_VSEG_SIZE * header->vsegs +
743            MAPPING_TASK_SIZE * header->tasks +
744            MAPPING_PROC_SIZE * header->procs +
745            MAPPING_IRQ_SIZE * header->irqs +
746            MAPPING_COPROC_SIZE * header->coprocs +
747            MAPPING_CP_PORT_SIZE * header->cp_ports);
748}
749
[399]750///////////////////////////////////////////////////////////////////////////////////
[442]751//             Miscelaneous functions
[399]752///////////////////////////////////////////////////////////////////////////////////
753
[442]754//////////////////////////////////////
755__attribute__((noreturn)) void _exit() 
756{
757    unsigned int procid     = _get_procid();
758    unsigned int x          = (procid >> (Y_WIDTH + P_WIDTH)) & ((1<<X_WIDTH)-1);
759    unsigned int y          = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
760    unsigned int lpid       = procid & ((1<<P_WIDTH)-1);
761
762
763    _puts("\n[GIET PANIC] processor[");
764    _putd( x );
765    _puts(",");
766    _putd( y );
767    _puts(",");
768    _putd( lpid );
769    _puts("] exit at cycle");
770    _putd( _get_proctime() );
771    _puts(" ...\n");
772
773    while (1) { asm volatile ("nop"); }
774}
775
776/////////////////////////////////////
[399]777void _random_wait( unsigned int val )
778{
779    unsigned int mask  = (1<<(val&0x1F))-1;
780    unsigned int delay = (_get_proctime() ^ (_get_procid()<<4)) & mask;
781    asm volatile( "move  $3,   %0                 \n"
782                  "loop_nic_completed:            \n"
783                  "addi  $3,   $3, -1             \n"
784                  "bnez  $3,   loop_nic_completed \n"
785                  "nop                            \n"
786                  :
787                  : "r" (delay)
788                  : "$3" ); 
789}
[442]790
791///////////////////////////
[399]792void _break( char* string ) 
793{
794    char byte;
795
[442]796    _puts("\n[GIET DEBUG] break from ");
797    _puts( string );
798    _puts(" / stoke any key to continue\n");
[399]799    _getc( &byte );
800}
801
[442]802///////////////////////////////////////
[399]803unsigned int _strncmp( const char * s1, 
804                       const char * s2, 
805                       unsigned int n ) 
806{
807    unsigned int i;
808    for (i = 0; i < n; i++) 
809    {
810        if (s1[i] != s2[i])  return 1; 
811        if (s1[i] == 0)      break;
812    }
813    return 0;
814}
815
[442]816/////////////////////////////////////////
[399]817char* _strcpy( char* dest, char* source )
818{
819    if (!dest || !source) return dest;
820
821    while (*source)
822        *(dest++) = *(source++);
823
824    return dest;
825}
826
[442]827/////////////////////////////////////////////////////
[408]828void _dcache_buf_invalidate( unsigned int buf_vbase, 
829                             unsigned int buf_size ) 
[399]830{
[408]831    unsigned int offset;
[399]832    unsigned int tmp;
[408]833    unsigned int line_size;   // bytes
[399]834
835    // compute data cache line size based on config register (bits 12:10)
836    asm volatile(
837                 "mfc0 %0, $16, 1" 
838                 : "=r" (tmp) );
[408]839
[399]840    tmp = ((tmp >> 10) & 0x7);
841    line_size = 2 << tmp;
842
843    // iterate on cache lines
[408]844    for ( offset = 0; offset < buf_size; offset += line_size) 
[399]845    {
[408]846        _set_mmu_dcache_inval( buf_vbase + offset );
[399]847    }
848}
849
850
851
852///////////////////////////////////////////////////////////////////////////////////
853//   Required by GCC
854///////////////////////////////////////////////////////////////////////////////////
855
[442]856////////////////////////////////
[399]857void* memcpy( void*        dest,     // dest buffer vbase
858              const void*  source,   // source buffer vbase
859              unsigned int size )    // bytes
860{
861    unsigned int* idst = (unsigned int*)dest;
862    unsigned int* isrc = (unsigned int*)source;
863
864    // word-by-word copy
865    if (!((unsigned int) idst & 3) && !((unsigned int) isrc & 3)) 
866    {
867        while (size > 3) 
868        {
869            *idst++ = *isrc++;
870            size -= 4;
871        }
872    }
873
874    unsigned char* cdst = (unsigned char*)dest;
875    unsigned char* csrc = (unsigned char*)source;
876
877    /* byte-by-byte copy */
878    while (size--) 
879    {
880        *cdst++ = *csrc++;
881    }
882    return dest;
883}
[442]884
885/////////////////////////////////
886void * memset( void*        dst, 
887               int          value, 
888               unsigned int count ) 
[399]889{
890    // word-by-word copy
[442]891    unsigned int* idst = dst;
[399]892    unsigned int  data = (((unsigned char)value)      ) |
893                         (((unsigned char)value) <<  8) |
894                         (((unsigned char)value) << 16) |
895                         (((unsigned char)value) << 24) ;
896
897    if ( ! ((unsigned int)idst & 3) )
898    {
899        while ( count > 3 )
900        {
901            *idst++ = data;
902            count -= 4;
903        }
904    }
905   
906    // byte-by-byte copy
[442]907    unsigned char* cdst = dst;
[399]908    while (count--) 
909    {
910        *cdst++ = (unsigned char)value;
911    }
[442]912    return dst;
[399]913}
914
915
[258]916// Local Variables:
917// tab-width: 4
918// c-basic-offset: 4
919// c-file-offsets:((innamespace . 0)(inline-open . 0))
920// indent-tabs-mode: nil
921// End:
922// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
923
Note: See TracBrowser for help on using the repository browser.