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

Last change on this file since 218 was 215, checked in by karaoui, 12 years ago

New components are now mandotory in the XML description:

The files giet_vsegs.ld and hard_config.h are now autogenerated by the xml2bin tool.

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