source: soft/giet_vm/sys/common.c @ 192

Last change on this file since 192 was 189, checked in by alain, 12 years ago

Introducing a new release where all initialisation
is done in the boot code.

File size: 15.2 KB
RevLine 
[158]1///////////////////////////////////////////////////////////////////////////////////
2// File     : common.c
3// Date     : 01/04/2012
4// Author   : alain greiner and joel porquet
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// The common.c and common.h files are part of the GIET nano-kernel.
8// They contains various utilities functions.
9///////////////////////////////////////////////////////////////////////////////////
10
[165]11#include <sys_handler.h>
[158]12#include <common.h>
[189]13#include <ctx_handler.h>
[158]14#include <drivers.h>
15#include <stdarg.h>
16
[189]17///////////////////////////////////////////////////////////////////////////////////
18//      Global variables
19///////////////////////////////////////////////////////////////////////////////////
20
21// current context cache TODO
22
23// SR save (used by _it_mask() / it_restore()
24unsigned int    _status_register_save;
25
26///////////////////////////////////////////////////////////////////////////////////
27//        _get_sched()
28// Access CP0 and returns scheduler physical address.
29///////////////////////////////////////////////////////////////////////////////////
30inline unsigned int _get_sched()
31{
32    unsigned int ret;
33    asm volatile (      "mfc0   %0,             $22" 
34                                        : "=r"(ret) );
35    return ret;
36}
37///////////////////////////////////////////////////////////////////////////////////
38//        _get_ptpr()
39// Access CP2 and returns PTPR register.
40///////////////////////////////////////////////////////////////////////////////////
41inline unsigned int _get_ptpr()
42{
43    unsigned int ret;
44    asm volatile (      "mfc2   %0,             $0" 
45                                        : "=r"(ret) );
46    return ret;
47}
48///////////////////////////////////////////////////////////////////////////////////
49//        _get_epc()
50// Access CP0 and returns EPC register.
51///////////////////////////////////////////////////////////////////////////////////
52inline unsigned int _get_epc()
53{
54    unsigned int ret;
55    asm volatile (      "mfc0   %0,             $14" 
56                                        : "=r"(ret) );
57    return ret;
58}
59///////////////////////////////////////////////////////////////////////////////////
60//        _get_bar()
61// Access CP0 and returns BAR register.
62///////////////////////////////////////////////////////////////////////////////////
63inline unsigned int _get_bvar()
64{
65    unsigned int ret;
66    asm volatile (      "mfc0   %0,             $8" 
67                                        : "=r"(ret) );
68    return ret;
69}
70///////////////////////////////////////////////////////////////////////////////////
71//        _get_cr()
72// Access CP0 and returns CR register.
73///////////////////////////////////////////////////////////////////////////////////
74inline unsigned int _get_cause()
75{
76    unsigned int ret;
77    asm volatile (      "mfc0   %0,             $13" 
78                                        : "=r"(ret) );
79    return ret;
80}
81///////////////////////////////////////////////////////////////////////////////////
82//        _get_sr()
83// Access CP0 and returns SR register.
84///////////////////////////////////////////////////////////////////////////////////
85inline unsigned int _get_sr()
86{
87    unsigned int ret;
88    asm volatile (      "mfc0   %0,             $12" 
89                                        : "=r"(ret) );
90    return ret;
91}
92///////////////////////////////////////////////////////////////////////////////////
93//    _it_mask()
94// Access CP0 and mask IRQs
95///////////////////////////////////////////////////////////////////////////////////
96inline void _it_mask()
97{
98    unsigned int        sr_value;
99    asm volatile(       "li             $3,             0xFFFFFFFE      \n"
100                                        "mfc0   %0,             $12                     \n"
101                                        "and    $3,             $3, %0          \n"
102                                        "mtc0   $3,             $12                     \n"
103                                        : "=r"(sr_value) : : "$3" );
104    _status_register_save = sr_value;
105}
106///////////////////////////////////////////////////////////////////////////////////
107//    _it_enable()
108// Access CP0 and enable IRQs
109///////////////////////////////////////////////////////////////////////////////////
110inline void _it_restore()
111{
112    unsigned int        sr_value = _status_register_save;
113    asm volatile(       "mtc0  %0,              $12                     \n"
114                                        : : "r"(sr_value) );
115}
[158]116////////////////////////////////////////////////////////////////////////////
[189]117//    _get_lock()
118// Takes a lock with an ll/sc atomic access.
119// A pseudo random delay is introduced before retry in case of miss
120// (delay average value = 100 cycles)
[165]121////////////////////////////////////////////////////////////////////////////
122inline void _get_lock( unsigned int* plock )
123{
[189]124    register unsigned int  delay = ( _proctime() ^ _procid()<<4 ) & 0xFF;
[165]125
126    asm volatile (
127            "_lock_llsc:             \n"
128            "ll   $2,    0(%0)       \n" /* $2 <= _ioc_lock current value */
129            "bnez $2,    _lock_delay \n" /* delay if _ioc_lock already taken */
130            "li   $3,    1           \n" /* $3 <= argument for sc */
131            "sc   $3,    0(%0)       \n" /* try to set _ioc_lock */
132            "bnez $3,    _lock_ok    \n" /* exit if atomic */
133            "_lock_delay:            \n"
134            "move $4,    %1          \n" /* $4 <= delay */
135            "_lock_loop:             \n"
136            "addi $4,    $4,    -1   \n" /* $4 <= $4 - 1 */
137            "beqz $4,    _lock_loop  \n" /* test end delay */
138            "j           _lock_llsc  \n" /* retry */
139            "_lock_ok:               \n"
140            :
141            :"r"(plock), "r"(delay)
142            :"$2", "$3", "$4");
143}
144
145////////////////////////////////////////////////////////////////////////////
146// _release_lock()
147////////////////////////////////////////////////////////////////////////////
148inline void _release_lock( unsigned int* plock )
149{
150    *plock = 0;
151}
152
153////////////////////////////////////////////////////////////////////////////
[189]154//    _puts()
155// display a string on TTY0 / used for system code debugand log
[158]156////////////////////////////////////////////////////////////////////////////
157void _puts(char *buffer) 
158{
159    unsigned int* tty_address = (unsigned int*)&seg_tty_base;
160    unsigned int n;
161
162    for ( n=0; n<100; n++)
163    {
164        if (buffer[n] == 0) break;
165        tty_address[0] = (unsigned int)buffer[n];
166    }
167}
168////////////////////////////////////////////////////////////////////////////
[189]169//    _putw()
170// display an int (hexa) on TTY0 / used for system code debug and log
[158]171////////////////////////////////////////////////////////////////////////////
172void _putw(unsigned int val)
173{
174    static const char   HexaTab[] = "0123456789ABCDEF";
175    char                buf[11];
176    unsigned int        c;
177
178    buf[0]  = '0';
179    buf[1]  = 'x';
180    buf[10] = 0;
181
182    for ( c = 0 ; c < 8 ; c++ )
183    { 
184        buf[9-c] = HexaTab[val&0xF];
185        val = val >> 4;
186    }
187    _puts(buf);
188}
189////////////////////////////////////////////////////////////////////////////
[189]190//    _putd()
191// display an int (decimal) on TTY0 / used for system code debug and log
192////////////////////////////////////////////////////////////////////////////
193void _putd(unsigned int val)
194{
195    static const char   DecTab[] = "0123456789";
196    char                                buf[11];
197    unsigned int                i;
198    unsigned int                first;
199
200    buf[10] = 0;
201
202    for (i = 0; i < 10; i++)
203    {
204        if ((val != 0) || (i == 0))
205        {
206            buf[9-i] = DecTab[val % 10];
207            first    = 9-i;
208        }
209        else
210        {
211            break;
212        }
213        val /= 10;
214    }
215    _puts( &buf[first] );
216}
217////////////////////////////////////////////////////////////////////////////
218//    _strncmp()
[158]219// compare two strings s1 & s2 (no more than n characters)
220////////////////////////////////////////////////////////////////////////////
221unsigned int _strncmp(const char* s1, 
222                      const char* s2, 
223                      unsigned int n)
224{
225    unsigned int i;
226    for ( i=0 ; i<n ; i++)
227    {
228        if ( s1[i] != s2[i] ) return 1;
229        if ( s1[i] == 0 )     break;
230    }
231    return 0;
232}
233////////////////////////////////////////////////////////////////////////////
[189]234//         _dcache_buf_invalidate()
[158]235// Invalidate all data cache lines corresponding to a memory
236// buffer (identified by an address and a size).
237////////////////////////////////////////////////////////////////////////////
238void _dcache_buf_invalidate(const void *buffer, 
239                            unsigned int size)
240{
241    unsigned int i;
242    unsigned int tmp;
243    unsigned int line_size;
244
[166]245    // compute data cache line size based on config register (bits 12:10)
[158]246    asm volatile("mfc0 %0, $16, 1" : "=r"(tmp));
247    tmp = ((tmp>>10) & 0x7);
248    line_size = 2 << tmp;
249
[166]250    // iterate on cache lines
[158]251    for (i = 0; i < size; i += line_size)
252    {
253        asm volatile(
254                " cache %0, %1"
255                ::"i" (0x11), "R" (*((unsigned char*)buffer+i))
256                );
257    }
258}
[189]259////////////////////////////////////////////////////////////////////////////
260//    _physical_read_access()
261// This function makes a physical read access to a 32 bits word in memory,
262// after a temporary DTLB desactivation.
263////////////////////////////////////////////////////////////////////////////
264unsigned int _physical_read_access(unsigned int* paddr)
[158]265{
[189]266    unsigned int value;
[158]267
[189]268    asm volatile(   "li     $3,     0xFFFFFFFE          \n"
269                    "mfc0   $2,     $12                         \n"             /* $2 <= SR        */
270                    "and    $3,     $3,         $2              \n"
271                    "mtc0   $3,     $12                         \n"             /* interrupt masked */
272                    "li         $3,             0xB                             \n"
273                    "mtc2       $3,             $1                              \n"             /* DTLB off                     */     
274
275                    "lw         %0,             0(%1)                   \n"             /* entry <= *pslot      */
276
277                    "li         $3,             0xF                             \n"
278                    "mtc2       $3,             $1                              \n"             /* DTLB on                      */     
279                    "mtc0       $2,             $12                             \n"             /* restore SR           */
280                    : "=r"(value)
281                    : "r"(paddr)
282                    : "$2", "$3" );
283    return value;
[158]284}
[189]285////////////////////////////////////////////////////////////////////////////
286//    _physical_write_access()
287// This function makes a physical write access to a 32 bits word in memory,
288// after a temporary DTLB desactivation.
289////////////////////////////////////////////////////////////////////////////
290void _physical_write_access(unsigned int* paddr, unsigned int value)
[158]291{
[189]292    asm volatile(   "li     $3,     0xFFFFFFFE          \n"
293                    "mfc0   $2,     $12                         \n"             /* $26 <= SR        */
294                    "and    $3,     $3,         $2              \n"
295                    "mtc0   $3,     $12                         \n"             /* interrupt masked */
296                    "li         $3,             0xB                             \n"
297                    "mtc2       $3,             $1                              \n"             /* DTLB off                     */
298       
299                    "sw         %0,             0(%1)                   \n"             /* entry <= *pslot      */
[158]300
[189]301                    "li         $3,             0xF                             \n"
302                    "mtc2       $3,             $1                              \n"             /* DTLB on                      */     
303                    "mtc0       $2,             $12                             \n"             /* restore SR           */
304                    :
305                    : "r"(value), "r"(paddr)
306                    : "$2", "$3" );
[158]307}
[189]308////////////////////////////////////////////////////////////////////////////
309//    _get_tasks_number()
310// This function returns the number of tasks allocated to processor.
311////////////////////////////////////////////////////////////////////////////
312unsigned int _get_tasks_number()
[166]313{
[189]314    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
315    return _physical_read_access( &(psched->tasks) );
[166]316}
[189]317////////////////////////////////////////////////////////////////////////////
318//    _get_current_task_id()
319// This function returns the index of the currently running task.
320////////////////////////////////////////////////////////////////////////////
321unsigned int _get_current_task_id()
[158]322{
[189]323    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
324    return _physical_read_access( &(psched->current) );
[158]325}
[189]326///////////////////////////////////////////////////////////////////////////////
327//    _get_current_context_slot()
328// This function returns the global TTY index for the currently running task.
329///////////////////////////////////////////////////////////////////////////////
330unsigned int _get_current_context_slot(unsigned int slot_id)
[158]331{
[189]332    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
333    unsigned int                        current = _physical_read_access( &(psched->current) );
334    return _physical_read_access( &(psched->context[current][slot_id]) );
[158]335}
[189]336/////////////////////////////////////////////i//////////////////////////////////
337//    _get_interrupt_vector_entry()
338// This function returns the interrupt_vector entry defined by argument index.
339////////////////////////////////////////////////////////////////////////////////
340unsigned int _get_interrupt_vector_entry( unsigned int index )
[158]341{
[189]342    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
343    return _physical_read_access( &(psched->interrupt_vector[index]) );
[158]344}
[189]345////////////////////////////////////////////////////////////////////////////
346//    _set_current_task_id()
347// This function returns the index of the currently running task.
348////////////////////////////////////////////////////////////////////////////
349void _set_current_task_id( unsigned int value )
[158]350{
[189]351    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
352    _physical_write_access( &(psched->current), value );
[158]353}
[165]354
[158]355/////////////////////////////////////////////////////////////////////////////
356//      access functions to mapping_info data structure
357/////////////////////////////////////////////////////////////////////////////
358mapping_cluster_t* _get_cluster_base( mapping_header_t* header )
359{
360    return   (mapping_cluster_t*) ((char*)header +
361                                  MAPPING_HEADER_SIZE);
362}
363/////////////////////////////////////////////////////////////////////////////
364mapping_pseg_t* _get_pseg_base( mapping_header_t* header )
365{
366    return   (mapping_pseg_t*)    ((char*)header +
367                                  MAPPING_HEADER_SIZE +
368                                  MAPPING_CLUSTER_SIZE*header->clusters);
369}
370/////////////////////////////////////////////////////////////////////////////
371mapping_vspace_t* _get_vspace_base( mapping_header_t* header )
372{
373    return   (mapping_vspace_t*)  ((char*)header +
374                                  MAPPING_HEADER_SIZE +
375                                  MAPPING_CLUSTER_SIZE*header->clusters +
376                                  MAPPING_PSEG_SIZE*header->psegs);
377}
378/////////////////////////////////////////////////////////////////////////////
379mapping_vseg_t* _get_vseg_base( mapping_header_t* header )
380{
381    return   (mapping_vseg_t*)    ((char*)header +
382                                  MAPPING_HEADER_SIZE +
383                                  MAPPING_CLUSTER_SIZE*header->clusters +
384                                  MAPPING_PSEG_SIZE*header->psegs +
385                                  MAPPING_VSPACE_SIZE*header->vspaces);
386}
387/////////////////////////////////////////////////////////////////////////////
[160]388mapping_vobj_t* _get_vobj_base( mapping_header_t* header )
389{
390    return   (mapping_vobj_t*)   ((char*)header +
391                                  MAPPING_HEADER_SIZE +
392                                  MAPPING_CLUSTER_SIZE*header->clusters +
393                                  MAPPING_PSEG_SIZE*header->psegs +
394                                  MAPPING_VSPACE_SIZE*header->vspaces +
395                                  MAPPING_VSEG_SIZE*header->vsegs );
396}
397/////////////////////////////////////////////////////////////////////////////
[158]398mapping_task_t* _get_task_base( mapping_header_t* header )
399{
400    return   (mapping_task_t*)    ((char*)header +
401                                  MAPPING_HEADER_SIZE +
402                                  MAPPING_CLUSTER_SIZE*header->clusters +
403                                  MAPPING_PSEG_SIZE*header->psegs +
404                                  MAPPING_VSPACE_SIZE*header->vspaces +
[160]405                                  MAPPING_VOBJ_SIZE*header->vobjs +
[158]406                                  MAPPING_VSEG_SIZE*header->vsegs);
407}
408
Note: See TracBrowser for help on using the repository browser.