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

Last change on this file since 238 was 238, checked in by alain, 11 years ago

Major evolution to support physical addresses larger than 32 bits.
The map.xml format has been modified: the vsegs associated to schedulers
are now explicitely defined and mapped in the page tables.

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