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

Last change on this file since 252 was 240, checked in by joannou, 11 years ago

Bug fix for scheduler handling :

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