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

Last change on this file since 231 was 231, checked in by joannou, 11 years ago
  • Bugfix in Interruption mechanism :
    • _it_mask() and _it_restore() functions now share a global array indexed by the proc_id (used a simple global variable before => problem with multiproc)
    • added 2 new fuctions _it_enable() and _it_disable() that only affect the IE bit of the status register in COP0
    • replaced interrupt masking/restoring arround _ctx_switch() in sys_handler by a simple interrupt disabling before the call to _ctx_switch (restoring after a _ctx_switch wouldn't restore the correct task's status register)
    • replaced the use of _ctx_switch in _exit() by a call to _context_switch() (this function actually does the interrupt disabling)
  • Added some comments in the ctx_handler.h
  • Added the delay reset in the idle task (ctx_handler.c)
  • Added a new irq type (PTI)
    • Modifications in xml_parser.c to accept PTI irq type (now used in xml mappings)
    • Added the test on the irq type in the _irq_demux() function. This leads to a different argument passed to the ISR (i.e. either channel_id or irq_id (aka icuid) )
File size: 17.6 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()
[231]25unsigned int _status_register_save[NB_CLUSTERS*NB_PROCS_MAX];
[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
[231]105// This function uses a global _status_register_save array
106// This function is NOT USED and NOT TESTED
[189]107///////////////////////////////////////////////////////////////////////////////////
[228]108inline void _it_mask() {
109    unsigned int sr_value;
[231]110    unsigned int proc_id;
[228]111    asm volatile(
112            "li      $3,        0xFFFFFFFE    \n"
113            "mfc0    %0,        $12           \n"
114            "and     $3,        $3, %0        \n"
115            "mtc0    $3,        $12           \n"
[231]116            "mfc0    %1,        $15, 1        \n"
117            : "=r"(sr_value), "=r"(proc_id)
[228]118            : 
119            : "$3");
[231]120    _status_register_save[proc_id] = sr_value;
[189]121}
[228]122
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///////////////////////////////////////////////////////////////////////////////////
[228]130inline void _it_restore() {
[231]131    unsigned int proc_id;
132    // get the processor id to index the _status_register_save table
133    asm volatile("mfc0 %0, $15, 1" : "=r" (proc_id));
134    // restore the saved value into the status register
135    asm volatile("mtc0  %0, $12" : : "r" (_status_register_save[proc_id]));
136}
137
138///////////////////////////////////////////////////////////////////////////////////
139//    _it_disable()
140// Access CP0 and disables IRQs
141///////////////////////////////////////////////////////////////////////////////////
142inline void _it_disable() {
[228]143    asm volatile(
[231]144            "li      $3,        0xFFFFFFFE    \n"
145            "mfc0    $4,        $12           \n"
146            "and     $3,        $3, $4        \n"
147            "mtc0    $3,        $12           \n"
148            ::: "$3", "$4");
[189]149}
[228]150
[231]151///////////////////////////////////////////////////////////////////////////////////
152//    _it_enable()
153// Access CP0 and enables IRQs
154///////////////////////////////////////////////////////////////////////////////////
155inline void _it_enable() {
156    asm volatile(
157            "li      $3,        0x00000001    \n"
158            "mfc0    $4,        $12           \n"
159            "or      $3,        $3, $4        \n"
160            "mtc0    $3,        $12           \n"
161            ::: "$3", "$4");
162}
[228]163
[231]164
[158]165////////////////////////////////////////////////////////////////////////////
[189]166//    _get_lock()
167// Takes a lock with an ll/sc atomic access.
168// A pseudo random delay is introduced before retry in case of miss
169// (delay average value = 100 cycles)
[165]170////////////////////////////////////////////////////////////////////////////
[228]171inline void _get_lock(unsigned int * plock) {
172    register unsigned int delay = ( _proctime() ^ _procid() << 4) & 0xFF;
[165]173
174    asm volatile (
175            "_lock_llsc:             \n"
176            "ll   $2,    0(%0)       \n" /* $2 <= _ioc_lock current value */
177            "bnez $2,    _lock_delay \n" /* delay if _ioc_lock already taken */
178            "li   $3,    1           \n" /* $3 <= argument for sc */
179            "sc   $3,    0(%0)       \n" /* try to set _ioc_lock */
180            "bnez $3,    _lock_ok    \n" /* exit if atomic */
181            "_lock_delay:            \n"
182            "move $4,    %1          \n" /* $4 <= delay */
183            "_lock_loop:             \n"
184            "addi $4,    $4,    -1   \n" /* $4 <= $4 - 1 */
185            "beqz $4,    _lock_loop  \n" /* test end delay */
186            "j           _lock_llsc  \n" /* retry */
187            "_lock_ok:               \n"
188            :
189            :"r"(plock), "r"(delay)
190            :"$2", "$3", "$4");
191}
192
[228]193
[165]194////////////////////////////////////////////////////////////////////////////
195// _release_lock()
196////////////////////////////////////////////////////////////////////////////
[228]197inline void _release_lock(unsigned int * plock) {
[221]198    asm volatile (
[228]199            "sync\n" /* necessary because of the consistency model in tsar */
200            );
[165]201    *plock = 0;
202}
203
[228]204
[165]205////////////////////////////////////////////////////////////////////////////
[189]206//    _puts()
[207]207// display a string on TTY0 / used for system code debug and log
[158]208////////////////////////////////////////////////////////////////////////////
[228]209void _puts(char * buffer) {
210    unsigned int * tty_address = (unsigned int *) &seg_tty_base;
[158]211    unsigned int n;
212
[228]213    for (n = 0; n < 100; n++) {
214        if (buffer[n] == 0) {
215            break;
216        }
217        tty_address[TTY_WRITE] = (unsigned int) buffer[n];
[158]218    }
219}
[228]220
221
[158]222////////////////////////////////////////////////////////////////////////////
[207]223//    _putx()
[189]224// display an int (hexa) on TTY0 / used for system code debug and log
[158]225////////////////////////////////////////////////////////////////////////////
[228]226void _putx(unsigned int val) {
227    static const char HexaTab[] = "0123456789ABCDEF";
228    char buf[11];
229    unsigned int c;
[158]230
[228]231    buf[0] = '0';
232    buf[1] = 'x';
[158]233    buf[10] = 0;
234
[228]235    for (c = 0; c < 8; c++) { 
236        buf[9 - c] = HexaTab[val & 0xF];
[158]237        val = val >> 4;
238    }
239    _puts(buf);
240}
[228]241
242
[158]243////////////////////////////////////////////////////////////////////////////
[189]244//    _putd()
245// display an int (decimal) on TTY0 / used for system code debug and log
246////////////////////////////////////////////////////////////////////////////
[228]247void _putd(unsigned int val) {
248    static const char DecTab[] = "0123456789";
249    char buf[11];
250    unsigned int i;
251    unsigned int first;
[189]252
253    buf[10] = 0;
254
[228]255    for (i = 0; i < 10; i++) {
256        if ((val != 0) || (i == 0)) {
257            buf[9 - i] = DecTab[val % 10];
258            first = 9 - i;
[189]259        }
[228]260        else {
[189]261            break;
262        }
263        val /= 10;
264    }
[228]265    _puts(&buf[first]);
[189]266}
[228]267
268
[189]269////////////////////////////////////////////////////////////////////////////
270//    _strncmp()
[158]271// compare two strings s1 & s2 (no more than n characters)
272////////////////////////////////////////////////////////////////////////////
[228]273unsigned int _strncmp(const char * s1, const char * s2, unsigned int n) {
[158]274    unsigned int i;
[228]275    for (i = 0; i < n; i++) {
276        if (s1[i] != s2[i]) {
277            return 1;
278        }
279        if (s1[i] == 0) {
280            break;
281        }
[158]282    }
283    return 0;
284}
[228]285
286
[158]287////////////////////////////////////////////////////////////////////////////
[228]288//        _dcache_buf_invalidate()
[158]289// Invalidate all data cache lines corresponding to a memory
290// buffer (identified by an address and a size).
291////////////////////////////////////////////////////////////////////////////
[228]292void _dcache_buf_invalidate(const void * buffer, unsigned int size) {
[158]293    unsigned int i;
294    unsigned int tmp;
295    unsigned int line_size;
296
[166]297    // compute data cache line size based on config register (bits 12:10)
[228]298    asm volatile("mfc0 %0, $16, 1" : "=r" (tmp));
299    tmp = ((tmp >> 10) & 0x7);
[158]300    line_size = 2 << tmp;
301
[166]302    // iterate on cache lines
[228]303    for (i = 0; i < size; i += line_size) {
[158]304        asm volatile(
305                " cache %0, %1"
[228]306                :
307                :"i" (0x11), "R" (*((unsigned char *) buffer + i))
[158]308                );
309    }
310}
[228]311
312
[189]313////////////////////////////////////////////////////////////////////////////
314//    _physical_read_access()
315// This function makes a physical read access to a 32 bits word in memory,
316// after a temporary DTLB desactivation.
317////////////////////////////////////////////////////////////////////////////
[228]318unsigned int _physical_read_access(unsigned int * paddr) {
[189]319    unsigned int value;
[158]320
[228]321    asm volatile(
322            "li     $3,     0xFFFFFFFE         \n"
323            "mfc0   $2,     $12                \n"        /* $2 <= SR        */
324            "and    $3,     $3,        $2      \n"
325            "mtc0   $3,     $12                \n"        /* interrupt masked */
326            "li     $3,     0xB                \n"
327            "mtc2   $3,     $1                 \n"        /* DTLB off            */   
[189]328
[228]329            "lw     %0,     0(%1)              \n"        /* entry <= *pslot    */
[189]330
[228]331            "li     $3,     0xF                \n"
332            "mtc2   $3,     $1                 \n"        /* DTLB on             */   
333            "mtc0   $2,     $12                \n"        /* restore SR        */
334            : "=r" (value)
335            : "r" (paddr)
336            : "$2", "$3");
[189]337    return value;
[158]338}
[228]339
340
[189]341////////////////////////////////////////////////////////////////////////////
342//    _physical_write_access()
343// This function makes a physical write access to a 32 bits word in memory,
344// after a temporary DTLB desactivation.
345////////////////////////////////////////////////////////////////////////////
[228]346void _physical_write_access(unsigned int * paddr, unsigned int value) {
347    asm volatile(
348            "li     $3,     0xFFFFFFFE         \n"
349            "mfc0   $2,     $12                \n"        /* $26 <= SR        */
350            "and    $3,     $3,        $2      \n"
351            "mtc0   $3,     $12                \n"        /* interrupt masked */
352            "li     $3,     0xB                \n"
353            "mtc2   $3,     $1                 \n"        /* DTLB off            */
[158]354
[228]355            "sw     %0,     0(%1)              \n"        /* entry <= *pslot    */
356
357            "li     $3,     0xF                \n"
358            "mtc2   $3,     $1                 \n"        /* DTLB on             */   
359            "mtc0   $2,     $12                \n"        /* restore SR        */
360            :
361            : "r" (value), "r" (paddr)
362            : "$2", "$3");
[158]363}
[228]364
365
[189]366////////////////////////////////////////////////////////////////////////////
367//    _get_tasks_number()
368// This function returns the number of tasks allocated to processor.
369////////////////////////////////////////////////////////////////////////////
[228]370unsigned int _get_tasks_number() {
371    static_scheduler_t * psched = (static_scheduler_t *) _get_sched();
372    return _physical_read_access(&(psched->tasks));
[166]373}
[228]374
375
[189]376////////////////////////////////////////////////////////////////////////////
377//    _get_current_task_id()
378// This function returns the index of the currently running task.
379////////////////////////////////////////////////////////////////////////////
[228]380unsigned int _get_current_task_id() {
381    static_scheduler_t * psched = (static_scheduler_t *) _get_sched();
382    return _physical_read_access(&(psched->current));
[158]383}
[228]384
385
[199]386////////////////////////////////////////////////////////////////////////////
387//    _set_current_task_id()
388// This function returns the index of the currently running task.
389////////////////////////////////////////////////////////////////////////////
[228]390void _set_current_task_id(unsigned int value) {
391    static_scheduler_t * psched = (static_scheduler_t *) _get_sched();
392    _physical_write_access(&(psched->current), value);
[199]393}
[228]394
395
[189]396///////////////////////////////////////////////////////////////////////////////
[199]397//    _get_context_slot()
398// This function returns a slot content for the task defined by task_id.
[189]399///////////////////////////////////////////////////////////////////////////////
[228]400unsigned int _get_context_slot(unsigned int task_id, unsigned int slot_id) {
401    static_scheduler_t * psched = (static_scheduler_t *) _get_sched();
402    return _physical_read_access(&(psched->context[task_id][slot_id]));
[158]403}
[228]404
405
[199]406///////////////////////////////////////////////////////////////////////////////
407//    _set_context_slot()
408// This function returns a slot content for the task defined by task_id.
409///////////////////////////////////////////////////////////////////////////////
410void _set_context_slot( unsigned int task_id,
[228]411        unsigned int slot_id,
412        unsigned int value) {
413    static_scheduler_t * psched = (static_scheduler_t *) _get_sched();
414    _physical_write_access(&(psched->context[task_id][slot_id]), value);
[199]415}
[228]416
417
[199]418////////////////////////////////////////////////////////////////////////////////
[189]419//    _get_interrupt_vector_entry()
420// This function returns the interrupt_vector entry defined by argument index.
421////////////////////////////////////////////////////////////////////////////////
[228]422unsigned int _get_interrupt_vector_entry(unsigned int index) {
423    static_scheduler_t * psched = (static_scheduler_t *) _get_sched();
424    return _physical_read_access( &(psched->interrupt_vector[index]));
[158]425}
[165]426
[228]427
[158]428/////////////////////////////////////////////////////////////////////////////
[228]429//      access functions to mapping_info data structure
[158]430/////////////////////////////////////////////////////////////////////////////
[228]431mapping_cluster_t * _get_cluster_base(mapping_header_t * header) {
432    return (mapping_cluster_t *) ((char *) header +
433            MAPPING_HEADER_SIZE);
[158]434}
[228]435
436
[158]437/////////////////////////////////////////////////////////////////////////////
[228]438mapping_pseg_t * _get_pseg_base(mapping_header_t * header) {
439    return (mapping_pseg_t *) ((char *) header +
440            MAPPING_HEADER_SIZE +
441            MAPPING_CLUSTER_SIZE * header->clusters);
[158]442}
443/////////////////////////////////////////////////////////////////////////////
[228]444mapping_vspace_t * _get_vspace_base(mapping_header_t * header) {
445    return (mapping_vspace_t *)  ((char *) header +
446            MAPPING_HEADER_SIZE +
447            MAPPING_CLUSTER_SIZE * header->clusters +
448            MAPPING_PSEG_SIZE * header->psegs);
[158]449}
[228]450
451
[158]452/////////////////////////////////////////////////////////////////////////////
[228]453mapping_vseg_t * _get_vseg_base(mapping_header_t * header)
[158]454{
[228]455    return (mapping_vseg_t *) ((char *) header +
456            MAPPING_HEADER_SIZE +
457            MAPPING_CLUSTER_SIZE * header->clusters +
458            MAPPING_PSEG_SIZE * header->psegs +
459            MAPPING_VSPACE_SIZE * header->vspaces);
[158]460}
[228]461
462
[158]463/////////////////////////////////////////////////////////////////////////////
[228]464mapping_vobj_t * _get_vobj_base(mapping_header_t * header) {
465    return (mapping_vobj_t *) ((char *) header +
466            MAPPING_HEADER_SIZE +
467            MAPPING_CLUSTER_SIZE * header->clusters +
468            MAPPING_PSEG_SIZE * header->psegs +
469            MAPPING_VSPACE_SIZE * header->vspaces +
470            MAPPING_VSEG_SIZE * header->vsegs );
[160]471}
[228]472
473
[160]474/////////////////////////////////////////////////////////////////////////////
[228]475mapping_task_t * _get_task_base(mapping_header_t * header) {
476    return (mapping_task_t *) ((char *) header +
477            MAPPING_HEADER_SIZE +
478            MAPPING_CLUSTER_SIZE * header->clusters +
479            MAPPING_PSEG_SIZE * header->psegs +
480            MAPPING_VSPACE_SIZE * header->vspaces +
481            MAPPING_VOBJ_SIZE * header->vobjs +
482            MAPPING_VSEG_SIZE * header->vsegs);
[158]483}
484
[228]485
486// Local Variables:
487// tab-width: 4
488// c-basic-offset: 4
489// c-file-offsets:((innamespace . 0)(inline-open . 0))
490// indent-tabs-mode: nil
491// End:
492// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
493
Note: See TracBrowser for help on using the repository browser.