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

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

Several bugs have been fixed to support TSAR multi-cluster architecture
such as the "tsarv4-generic_mmu" platform.

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*)( (char*)&seg_tty_base +
161                                (CLUSTER_IO_ID * (unsigned)CLUSTER_SIZE) ); 
162    unsigned int n;
163
164    for ( n=0; n<100; n++)
165    {
166        if (buffer[n] == 0) break;
167        tty_address[TTY_WRITE] = (unsigned int)buffer[n];
168    }
169}
170////////////////////////////////////////////////////////////////////////////
171//    _putx()
172// display an int (hexa) on TTY0 / used for system code debug and log
173////////////////////////////////////////////////////////////////////////////
174void _putx(unsigned int val)
175{
176    static const char   HexaTab[] = "0123456789ABCDEF";
177    char                buf[11];
178    unsigned int        c;
179
180    buf[0]  = '0';
181    buf[1]  = 'x';
182    buf[10] = 0;
183
184    for ( c = 0 ; c < 8 ; c++ )
185    { 
186        buf[9-c] = HexaTab[val&0xF];
187        val = val >> 4;
188    }
189    _puts(buf);
190}
191////////////////////////////////////////////////////////////////////////////
192//    _putd()
193// display an int (decimal) on TTY0 / used for system code debug and log
194////////////////////////////////////////////////////////////////////////////
195void _putd(unsigned int val)
196{
197    static const char   DecTab[] = "0123456789";
198    char                                buf[11];
199    unsigned int                i;
200    unsigned int                first;
201
202    buf[10] = 0;
203
204    for (i = 0; i < 10; i++)
205    {
206        if ((val != 0) || (i == 0))
207        {
208            buf[9-i] = DecTab[val % 10];
209            first    = 9-i;
210        }
211        else
212        {
213            break;
214        }
215        val /= 10;
216    }
217    _puts( &buf[first] );
218}
219////////////////////////////////////////////////////////////////////////////
220//    _strncmp()
221// compare two strings s1 & s2 (no more than n characters)
222////////////////////////////////////////////////////////////////////////////
223unsigned int _strncmp(const char* s1, 
224                      const char* s2, 
225                      unsigned int n)
226{
227    unsigned int i;
228    for ( i=0 ; i<n ; i++)
229    {
230        if ( s1[i] != s2[i] ) return 1;
231        if ( s1[i] == 0 )     break;
232    }
233    return 0;
234}
235////////////////////////////////////////////////////////////////////////////
236//         _dcache_buf_invalidate()
237// Invalidate all data cache lines corresponding to a memory
238// buffer (identified by an address and a size).
239////////////////////////////////////////////////////////////////////////////
240void _dcache_buf_invalidate(const void *buffer, 
241                            unsigned int size)
242{
243    unsigned int i;
244    unsigned int tmp;
245    unsigned int line_size;
246
247    // compute data cache line size based on config register (bits 12:10)
248    asm volatile("mfc0 %0, $16, 1" : "=r"(tmp));
249    tmp = ((tmp>>10) & 0x7);
250    line_size = 2 << tmp;
251
252    // iterate on cache lines
253    for (i = 0; i < size; i += line_size)
254    {
255        asm volatile(
256                " cache %0, %1"
257                ::"i" (0x11), "R" (*((unsigned char*)buffer+i))
258                );
259    }
260}
261////////////////////////////////////////////////////////////////////////////
262//    _physical_read_access()
263// This function makes a physical read access to a 32 bits word in memory,
264// after a temporary DTLB desactivation.
265////////////////////////////////////////////////////////////////////////////
266unsigned int _physical_read_access(unsigned int* paddr)
267{
268    unsigned int value;
269
270    asm volatile(   "li     $3,     0xFFFFFFFE          \n"
271                    "mfc0   $2,     $12                         \n"             /* $2 <= SR        */
272                    "and    $3,     $3,         $2              \n"
273                    "mtc0   $3,     $12                         \n"             /* interrupt masked */
274                    "li         $3,             0xB                             \n"
275                    "mtc2       $3,             $1                              \n"             /* DTLB off                     */     
276
277                    "lw         %0,             0(%1)                   \n"             /* entry <= *pslot      */
278
279                    "li         $3,             0xF                             \n"
280                    "mtc2       $3,             $1                              \n"             /* DTLB on                      */     
281                    "mtc0       $2,             $12                             \n"             /* restore SR           */
282                    : "=r"(value)
283                    : "r"(paddr)
284                    : "$2", "$3" );
285    return value;
286}
287////////////////////////////////////////////////////////////////////////////
288//    _physical_write_access()
289// This function makes a physical write access to a 32 bits word in memory,
290// after a temporary DTLB desactivation.
291////////////////////////////////////////////////////////////////////////////
292void _physical_write_access(unsigned int* paddr, unsigned int value)
293{
294    asm volatile(   "li     $3,     0xFFFFFFFE          \n"
295                    "mfc0   $2,     $12                         \n"             /* $26 <= SR        */
296                    "and    $3,     $3,         $2              \n"
297                    "mtc0   $3,     $12                         \n"             /* interrupt masked */
298                    "li         $3,             0xB                             \n"
299                    "mtc2       $3,             $1                              \n"             /* DTLB off                     */
300       
301                    "sw         %0,             0(%1)                   \n"             /* entry <= *pslot      */
302
303                    "li         $3,             0xF                             \n"
304                    "mtc2       $3,             $1                              \n"             /* DTLB on                      */     
305                    "mtc0       $2,             $12                             \n"             /* restore SR           */
306                    :
307                    : "r"(value), "r"(paddr)
308                    : "$2", "$3" );
309}
310////////////////////////////////////////////////////////////////////////////
311//    _get_tasks_number()
312// This function returns the number of tasks allocated to processor.
313////////////////////////////////////////////////////////////////////////////
314unsigned int _get_tasks_number()
315{
316    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
317    return _physical_read_access( &(psched->tasks) );
318}
319////////////////////////////////////////////////////////////////////////////
320//    _get_current_task_id()
321// This function returns the index of the currently running task.
322////////////////////////////////////////////////////////////////////////////
323unsigned int _get_current_task_id()
324{
325    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
326    return _physical_read_access( &(psched->current) );
327}
328////////////////////////////////////////////////////////////////////////////
329//    _set_current_task_id()
330// This function returns the index of the currently running task.
331////////////////////////////////////////////////////////////////////////////
332void _set_current_task_id( unsigned int value )
333{
334    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
335    _physical_write_access( &(psched->current), value );
336}
337///////////////////////////////////////////////////////////////////////////////
338//    _get_context_slot()
339// This function returns a slot content for the task defined by task_id.
340///////////////////////////////////////////////////////////////////////////////
341unsigned int _get_context_slot( unsigned int task_id,
342                                unsigned int slot_id )
343{
344    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
345    return _physical_read_access( &(psched->context[task_id][slot_id]) );
346}
347///////////////////////////////////////////////////////////////////////////////
348//    _set_context_slot()
349// This function returns a slot content for the task defined by task_id.
350///////////////////////////////////////////////////////////////////////////////
351void _set_context_slot( unsigned int task_id,
352                        unsigned int slot_id,
353                        unsigned int value )
354{
355    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
356    _physical_write_access( &(psched->context[task_id][slot_id]), value );
357}
358////////////////////////////////////////////////////////////////////////////////
359//    _get_interrupt_vector_entry()
360// This function returns the interrupt_vector entry defined by argument index.
361////////////////////////////////////////////////////////////////////////////////
362unsigned int _get_interrupt_vector_entry( unsigned int index )
363{
364    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
365    return _physical_read_access( &(psched->interrupt_vector[index]) );
366}
367
368/////////////////////////////////////////////////////////////////////////////
369//      access functions to mapping_info data structure
370/////////////////////////////////////////////////////////////////////////////
371mapping_cluster_t* _get_cluster_base( mapping_header_t* header )
372{
373    return   (mapping_cluster_t*) ((char*)header +
374                                  MAPPING_HEADER_SIZE);
375}
376/////////////////////////////////////////////////////////////////////////////
377mapping_pseg_t* _get_pseg_base( mapping_header_t* header )
378{
379    return   (mapping_pseg_t*)    ((char*)header +
380                                  MAPPING_HEADER_SIZE +
381                                  MAPPING_CLUSTER_SIZE*header->clusters);
382}
383/////////////////////////////////////////////////////////////////////////////
384mapping_vspace_t* _get_vspace_base( mapping_header_t* header )
385{
386    return   (mapping_vspace_t*)  ((char*)header +
387                                  MAPPING_HEADER_SIZE +
388                                  MAPPING_CLUSTER_SIZE*header->clusters +
389                                  MAPPING_PSEG_SIZE*header->psegs);
390}
391/////////////////////////////////////////////////////////////////////////////
392mapping_vseg_t* _get_vseg_base( mapping_header_t* header )
393{
394    return   (mapping_vseg_t*)    ((char*)header +
395                                  MAPPING_HEADER_SIZE +
396                                  MAPPING_CLUSTER_SIZE*header->clusters +
397                                  MAPPING_PSEG_SIZE*header->psegs +
398                                  MAPPING_VSPACE_SIZE*header->vspaces);
399}
400/////////////////////////////////////////////////////////////////////////////
401mapping_vobj_t* _get_vobj_base( mapping_header_t* header )
402{
403    return   (mapping_vobj_t*)   ((char*)header +
404                                  MAPPING_HEADER_SIZE +
405                                  MAPPING_CLUSTER_SIZE*header->clusters +
406                                  MAPPING_PSEG_SIZE*header->psegs +
407                                  MAPPING_VSPACE_SIZE*header->vspaces +
408                                  MAPPING_VSEG_SIZE*header->vsegs );
409}
410/////////////////////////////////////////////////////////////////////////////
411mapping_task_t* _get_task_base( mapping_header_t* header )
412{
413    return   (mapping_task_t*)    ((char*)header +
414                                  MAPPING_HEADER_SIZE +
415                                  MAPPING_CLUSTER_SIZE*header->clusters +
416                                  MAPPING_PSEG_SIZE*header->psegs +
417                                  MAPPING_VSPACE_SIZE*header->vspaces +
418                                  MAPPING_VOBJ_SIZE*header->vobjs +
419                                  MAPPING_VSEG_SIZE*header->vsegs);
420}
421
Note: See TracBrowser for help on using the repository browser.