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

Last change on this file since 228 was 228, checked in by meunier, 11 years ago

Added support for memspaces and const.
Added an interrupt masking to the "giet_context_switch" syscall
Corrected two bugs in boot/boot_init.c (one minor and one regarding barriers initialization)
Reformatted the code in all files.

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