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

Last change on this file since 200 was 199, checked in by alain, 12 years ago

Introducing the "idle" to improve the exit mechanism.

File size: 15.7 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 <stdarg.h>
16
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}
116////////////////////////////////////////////////////////////////////////////
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)
121////////////////////////////////////////////////////////////////////////////
122inline void _get_lock( unsigned int* plock )
123{
124    register unsigned int  delay = ( _proctime() ^ _procid()<<4 ) & 0xFF;
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////////////////////////////////////////////////////////////////////////////
154//    _puts()
155// display a string on TTY0 / used for system code debugand log
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////////////////////////////////////////////////////////////////////////////
169//    _putw()
170// display an int (hexa) on TTY0 / used for system code debug and log
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////////////////////////////////////////////////////////////////////////////
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()
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////////////////////////////////////////////////////////////////////////////
234//         _dcache_buf_invalidate()
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
245    // compute data cache line size based on config register (bits 12:10)
246    asm volatile("mfc0 %0, $16, 1" : "=r"(tmp));
247    tmp = ((tmp>>10) & 0x7);
248    line_size = 2 << tmp;
249
250    // iterate on cache lines
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}
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)
265{
266    unsigned int value;
267
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;
284}
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)
291{
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      */
300
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" );
307}
308////////////////////////////////////////////////////////////////////////////
309//    _get_tasks_number()
310// This function returns the number of tasks allocated to processor.
311////////////////////////////////////////////////////////////////////////////
312unsigned int _get_tasks_number()
313{
314    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
315    return _physical_read_access( &(psched->tasks) );
316}
317////////////////////////////////////////////////////////////////////////////
318//    _get_current_task_id()
319// This function returns the index of the currently running task.
320////////////////////////////////////////////////////////////////////////////
321unsigned int _get_current_task_id()
322{
323    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
324    return _physical_read_access( &(psched->current) );
325}
326////////////////////////////////////////////////////////////////////////////
327//    _set_current_task_id()
328// This function returns the index of the currently running task.
329////////////////////////////////////////////////////////////////////////////
330void _set_current_task_id( unsigned int value )
331{
332    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
333    _physical_write_access( &(psched->current), value );
334}
335///////////////////////////////////////////////////////////////////////////////
336//    _get_context_slot()
337// This function returns a slot content for the task defined by task_id.
338///////////////////////////////////////////////////////////////////////////////
339unsigned int _get_context_slot( unsigned int task_id,
340                                unsigned int slot_id )
341{
342    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
343    return _physical_read_access( &(psched->context[task_id][slot_id]) );
344}
345///////////////////////////////////////////////////////////////////////////////
346//    _set_context_slot()
347// This function returns a slot content for the task defined by task_id.
348///////////////////////////////////////////////////////////////////////////////
349void _set_context_slot( unsigned int task_id,
350                        unsigned int slot_id,
351                        unsigned int value )
352{
353    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
354    _physical_write_access( &(psched->context[task_id][slot_id]), value );
355}
356////////////////////////////////////////////////////////////////////////////////
357//    _get_interrupt_vector_entry()
358// This function returns the interrupt_vector entry defined by argument index.
359////////////////////////////////////////////////////////////////////////////////
360unsigned int _get_interrupt_vector_entry( unsigned int index )
361{
362    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
363    return _physical_read_access( &(psched->interrupt_vector[index]) );
364}
365
366/////////////////////////////////////////////////////////////////////////////
367//      access functions to mapping_info data structure
368/////////////////////////////////////////////////////////////////////////////
369mapping_cluster_t* _get_cluster_base( mapping_header_t* header )
370{
371    return   (mapping_cluster_t*) ((char*)header +
372                                  MAPPING_HEADER_SIZE);
373}
374/////////////////////////////////////////////////////////////////////////////
375mapping_pseg_t* _get_pseg_base( mapping_header_t* header )
376{
377    return   (mapping_pseg_t*)    ((char*)header +
378                                  MAPPING_HEADER_SIZE +
379                                  MAPPING_CLUSTER_SIZE*header->clusters);
380}
381/////////////////////////////////////////////////////////////////////////////
382mapping_vspace_t* _get_vspace_base( mapping_header_t* header )
383{
384    return   (mapping_vspace_t*)  ((char*)header +
385                                  MAPPING_HEADER_SIZE +
386                                  MAPPING_CLUSTER_SIZE*header->clusters +
387                                  MAPPING_PSEG_SIZE*header->psegs);
388}
389/////////////////////////////////////////////////////////////////////////////
390mapping_vseg_t* _get_vseg_base( mapping_header_t* header )
391{
392    return   (mapping_vseg_t*)    ((char*)header +
393                                  MAPPING_HEADER_SIZE +
394                                  MAPPING_CLUSTER_SIZE*header->clusters +
395                                  MAPPING_PSEG_SIZE*header->psegs +
396                                  MAPPING_VSPACE_SIZE*header->vspaces);
397}
398/////////////////////////////////////////////////////////////////////////////
399mapping_vobj_t* _get_vobj_base( mapping_header_t* header )
400{
401    return   (mapping_vobj_t*)   ((char*)header +
402                                  MAPPING_HEADER_SIZE +
403                                  MAPPING_CLUSTER_SIZE*header->clusters +
404                                  MAPPING_PSEG_SIZE*header->psegs +
405                                  MAPPING_VSPACE_SIZE*header->vspaces +
406                                  MAPPING_VSEG_SIZE*header->vsegs );
407}
408/////////////////////////////////////////////////////////////////////////////
409mapping_task_t* _get_task_base( mapping_header_t* header )
410{
411    return   (mapping_task_t*)    ((char*)header +
412                                  MAPPING_HEADER_SIZE +
413                                  MAPPING_CLUSTER_SIZE*header->clusters +
414                                  MAPPING_PSEG_SIZE*header->psegs +
415                                  MAPPING_VSPACE_SIZE*header->vspaces +
416                                  MAPPING_VOBJ_SIZE*header->vobjs +
417                                  MAPPING_VSEG_SIZE*header->vsegs);
418}
419
Note: See TracBrowser for help on using the repository browser.