Changeset 189 for soft/giet_vm/sys


Ignore:
Timestamp:
Aug 7, 2012, 6:37:49 PM (12 years ago)
Author:
alain
Message:

Introducing a new release where all initialisation
is done in the boot code.

Location:
soft/giet_vm/sys
Files:
16 edited

Legend:

Unmodified
Added
Removed
  • soft/giet_vm/sys/common.c

    r166 r189  
    1111#include <sys_handler.h>
    1212#include <common.h>
     13#include <ctx_handler.h>
    1314#include <drivers.h>
    1415#include <stdarg.h>
    1516
    16 ////////////////////////////////////////////////////////////////////////////
    17 // _get_lock()
     17///////////////////////////////////////////////////////////////////////////////////
     18//      Global variables
     19///////////////////////////////////////////////////////////////////////////////////
     20
     21// current context cache TODO
     22
     23// SR save (used by _it_mask() / it_restore()
     24unsigned int    _status_register_save;
     25
     26///////////////////////////////////////////////////////////////////////////////////
     27//        _get_sched()
     28// Access CP0 and returns scheduler physical address.
     29///////////////////////////////////////////////////////////////////////////////////
     30inline unsigned int _get_sched()
     31{
     32    unsigned int ret;
     33    asm volatile (      "mfc0   %0,             $22"
     34                                        : "=r"(ret) );
     35    return ret;
     36}
     37///////////////////////////////////////////////////////////////////////////////////
     38//        _get_ptpr()
     39// Access CP2 and returns PTPR register.
     40///////////////////////////////////////////////////////////////////////////////////
     41inline unsigned int _get_ptpr()
     42{
     43    unsigned int ret;
     44    asm volatile (      "mfc2   %0,             $0"
     45                                        : "=r"(ret) );
     46    return ret;
     47}
     48///////////////////////////////////////////////////////////////////////////////////
     49//        _get_epc()
     50// Access CP0 and returns EPC register.
     51///////////////////////////////////////////////////////////////////////////////////
     52inline unsigned int _get_epc()
     53{
     54    unsigned int ret;
     55    asm volatile (      "mfc0   %0,             $14"
     56                                        : "=r"(ret) );
     57    return ret;
     58}
     59///////////////////////////////////////////////////////////////////////////////////
     60//        _get_bar()
     61// Access CP0 and returns BAR register.
     62///////////////////////////////////////////////////////////////////////////////////
     63inline unsigned int _get_bvar()
     64{
     65    unsigned int ret;
     66    asm volatile (      "mfc0   %0,             $8"
     67                                        : "=r"(ret) );
     68    return ret;
     69}
     70///////////////////////////////////////////////////////////////////////////////////
     71//        _get_cr()
     72// Access CP0 and returns CR register.
     73///////////////////////////////////////////////////////////////////////////////////
     74inline unsigned int _get_cause()
     75{
     76    unsigned int ret;
     77    asm volatile (      "mfc0   %0,             $13"
     78                                        : "=r"(ret) );
     79    return ret;
     80}
     81///////////////////////////////////////////////////////////////////////////////////
     82//        _get_sr()
     83// Access CP0 and returns SR register.
     84///////////////////////////////////////////////////////////////////////////////////
     85inline unsigned int _get_sr()
     86{
     87    unsigned int ret;
     88    asm volatile (      "mfc0   %0,             $12"
     89                                        : "=r"(ret) );
     90    return ret;
     91}
     92///////////////////////////////////////////////////////////////////////////////////
     93//    _it_mask()
     94// Access CP0 and mask IRQs
     95///////////////////////////////////////////////////////////////////////////////////
     96inline void _it_mask()
     97{
     98    unsigned int        sr_value;
     99    asm volatile(       "li             $3,             0xFFFFFFFE      \n"
     100                                        "mfc0   %0,             $12                     \n"
     101                                        "and    $3,             $3, %0          \n"
     102                                        "mtc0   $3,             $12                     \n"
     103                                        : "=r"(sr_value) : : "$3" );
     104    _status_register_save = sr_value;
     105}
     106///////////////////////////////////////////////////////////////////////////////////
     107//    _it_enable()
     108// Access CP0 and enable IRQs
     109///////////////////////////////////////////////////////////////////////////////////
     110inline void _it_restore()
     111{
     112    unsigned int        sr_value = _status_register_save;
     113    asm volatile(       "mtc0  %0,              $12                     \n"
     114                                        : : "r"(sr_value) );
     115}
     116////////////////////////////////////////////////////////////////////////////
     117//    _get_lock()
     118// Takes a lock with an ll/sc atomic access.
     119// A pseudo random delay is introduced before retry in case of miss
     120// (delay average value = 100 cycles)
    18121////////////////////////////////////////////////////////////////////////////
    19122inline void _get_lock( unsigned int* plock )
    20123{
    21     register unsigned int  delay = (_proctime() & 0xF) << 4;
     124    register unsigned int  delay = ( _proctime() ^ _procid()<<4 ) & 0xFF;
    22125
    23126    asm volatile (
     
    49152
    50153////////////////////////////////////////////////////////////////////////////
    51 // _puts()
    52 // used for system code debug / it uses TTY0
     154//    _puts()
     155// display a string on TTY0 / used for system code debugand log
    53156////////////////////////////////////////////////////////////////////////////
    54157void _puts(char *buffer)
     
    64167}
    65168////////////////////////////////////////////////////////////////////////////
    66 // _putw()
    67 // used for system code debug / it uses TTY0
     169//    _putw()
     170// display an int (hexa) on TTY0 / used for system code debug and log
    68171////////////////////////////////////////////////////////////////////////////
    69172void _putw(unsigned int val)
     
    85188}
    86189////////////////////////////////////////////////////////////////////////////
    87 // _strncmp()
     190//    _putd()
     191// display an int (decimal) on TTY0 / used for system code debug and log
     192////////////////////////////////////////////////////////////////////////////
     193void _putd(unsigned int val)
     194{
     195    static const char   DecTab[] = "0123456789";
     196    char                                buf[11];
     197    unsigned int                i;
     198    unsigned int                first;
     199
     200    buf[10] = 0;
     201
     202    for (i = 0; i < 10; i++)
     203    {
     204        if ((val != 0) || (i == 0))
     205        {
     206            buf[9-i] = DecTab[val % 10];
     207            first    = 9-i;
     208        }
     209        else
     210        {
     211            break;
     212        }
     213        val /= 10;
     214    }
     215    _puts( &buf[first] );
     216}
     217////////////////////////////////////////////////////////////////////////////
     218//    _strncmp()
    88219// compare two strings s1 & s2 (no more than n characters)
    89220////////////////////////////////////////////////////////////////////////////
     
    101232}
    102233////////////////////////////////////////////////////////////////////////////
    103 //      _dcache_buf_invalidate()
     234//         _dcache_buf_invalidate()
    104235// Invalidate all data cache lines corresponding to a memory
    105236// buffer (identified by an address and a size).
     
    126257    }
    127258}
    128 ///////////////////////////////////////////////////////////////////////////////////
    129 //      _itoa_dec()
    130 // Convert a 32-bit unsigned integer to a string of ten decimal characters.
    131 ///////////////////////////////////////////////////////////////////////////////////
    132 void _itoa_dec(unsigned int val, char *buf)
    133 {
    134     const static char dectab[] = "0123456789";
    135     unsigned int i;
    136 
    137     for (i = 0; i < 10; i++)
    138     {
    139         if ((val != 0) || (i == 0))
    140             buf[9-i] = dectab[val % 10];
    141         else
    142             buf[9-i] = 0x20;
    143         val /= 10;
    144     }
    145 }
    146 ///////////////////////////////////////////////////////////////////////////////////
    147 //      _itoa_hex()
    148 // Convert a 32-bit unsigned integer to a string of eight hexadecimal characters.
    149 ///////////////////////////////////////////////////////////////////////////////////
    150 void _itoa_hex(unsigned int val, char *buf)
    151 {
    152     const static char hexatab[] = "0123456789ABCD";
    153     unsigned int i;
    154 
    155     for (i = 0; i < 8; i++)
    156     {
    157         buf[7-i] = hexatab[val % 16];
    158         val /= 16;
    159     }
    160 }
    161 ///////////////////////////////////////////////////////////////////////////////////
    162 //      _get_ptpr()
    163 // Access CP2 and returns PTPR register.
    164 ///////////////////////////////////////////////////////////////////////////////////
    165 inline unsigned int _get_ptpr()
    166 {
    167     unsigned int ret;
    168     asm volatile("mfc2 %0, $0" : "=r"(ret));
    169     return ret;
    170 }
    171 ///////////////////////////////////////////////////////////////////////////////////
    172 //      _get_epc()
    173 // Access CP0 and returns EPC register.
    174 ///////////////////////////////////////////////////////////////////////////////////
    175 inline unsigned int _get_epc()
    176 {
    177     unsigned int ret;
    178     asm volatile("mfc0 %0, $14" : "=r"(ret));
    179     return ret;
    180 }
    181 ///////////////////////////////////////////////////////////////////////////////////
    182 //      _get_bar()
    183 // Access CP0 and returns BAR register.
    184 ///////////////////////////////////////////////////////////////////////////////////
    185 inline unsigned int _get_bar()
    186 {
    187     unsigned int ret;
    188     asm volatile("mfc0 %0, $8" : "=r"(ret));
    189     return ret;
    190 }
    191 ///////////////////////////////////////////////////////////////////////////////////
    192 //      _get_cr()
    193 // Access CP0 and returns CR register.
    194 ///////////////////////////////////////////////////////////////////////////////////
    195 inline unsigned int _get_cause()
    196 {
    197     unsigned int ret;
    198     asm volatile("mfc0 %0, $13" : "=r"(ret));
    199     return ret;
    200 }
    201 
    202 ///////////////////////////////////////////////////////////////////////////////////
    203 //      _it_mask()
    204 // Access CP0 and mask IRQs
    205 ///////////////////////////////////////////////////////////////////////////////////
    206 inline void _it_mask()
    207 {
    208     asm volatile(
    209             "lui   $27,      0xFFFF   \n"
    210             "ori   $27, $27, 0xFFFE   \n"
    211             "mfc0  $26, $12           \n"
    212             "and   $26, $26, $27      \n"
    213             "mtc0  $26, $12           \n"
    214             ::: "$26", "$27"
    215             );
    216 }
    217 ///////////////////////////////////////////////////////////////////////////////////
    218 //      _it_enable()
    219 // Access CP0 and enable IRQs
    220 ///////////////////////////////////////////////////////////////////////////////////
    221 inline void _it_enable()
    222 {
    223     asm volatile(
    224             "mfc0  $26, $12      \n"
    225             "ori   $26, $26, 1   \n"
    226             "mtc0  $26, $12      \n"
    227             ::: "$26"
    228             );
     259////////////////////////////////////////////////////////////////////////////
     260//    _physical_read_access()
     261// This function makes a physical read access to a 32 bits word in memory,
     262// after a temporary DTLB desactivation.
     263////////////////////////////////////////////////////////////////////////////
     264unsigned int _physical_read_access(unsigned int* paddr)
     265{
     266    unsigned int value;
     267
     268    asm volatile(   "li     $3,     0xFFFFFFFE          \n"
     269                    "mfc0   $2,     $12                         \n"             /* $2 <= SR        */
     270                    "and    $3,     $3,         $2              \n"
     271                    "mtc0   $3,     $12                         \n"             /* interrupt masked */
     272                    "li         $3,             0xB                             \n"
     273                    "mtc2       $3,             $1                              \n"             /* DTLB off                     */     
     274
     275                    "lw         %0,             0(%1)                   \n"             /* entry <= *pslot      */
     276
     277                    "li         $3,             0xF                             \n"
     278                    "mtc2       $3,             $1                              \n"             /* DTLB on                      */     
     279                    "mtc0       $2,             $12                             \n"             /* restore SR           */
     280                    : "=r"(value)
     281                    : "r"(paddr)
     282                    : "$2", "$3" );
     283    return value;
     284}
     285////////////////////////////////////////////////////////////////////////////
     286//    _physical_write_access()
     287// This function makes a physical write access to a 32 bits word in memory,
     288// after a temporary DTLB desactivation.
     289////////////////////////////////////////////////////////////////////////////
     290void _physical_write_access(unsigned int* paddr, unsigned int value)
     291{
     292    asm volatile(   "li     $3,     0xFFFFFFFE          \n"
     293                    "mfc0   $2,     $12                         \n"             /* $26 <= SR        */
     294                    "and    $3,     $3,         $2              \n"
     295                    "mtc0   $3,     $12                         \n"             /* interrupt masked */
     296                    "li         $3,             0xB                             \n"
     297                    "mtc2       $3,             $1                              \n"             /* DTLB off                     */
     298       
     299                    "sw         %0,             0(%1)                   \n"             /* entry <= *pslot      */
     300
     301                    "li         $3,             0xF                             \n"
     302                    "mtc2       $3,             $1                              \n"             /* DTLB on                      */     
     303                    "mtc0       $2,             $12                             \n"             /* restore SR           */
     304                    :
     305                    : "r"(value), "r"(paddr)
     306                    : "$2", "$3" );
     307}
     308////////////////////////////////////////////////////////////////////////////
     309//    _get_tasks_number()
     310// This function returns the number of tasks allocated to processor.
     311////////////////////////////////////////////////////////////////////////////
     312unsigned int _get_tasks_number()
     313{
     314    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
     315    return _physical_read_access( &(psched->tasks) );
     316}
     317////////////////////////////////////////////////////////////////////////////
     318//    _get_current_task_id()
     319// This function returns the index of the currently running task.
     320////////////////////////////////////////////////////////////////////////////
     321unsigned int _get_current_task_id()
     322{
     323    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
     324    return _physical_read_access( &(psched->current) );
     325}
     326///////////////////////////////////////////////////////////////////////////////
     327//    _get_current_context_slot()
     328// This function returns the global TTY index for the currently running task.
     329///////////////////////////////////////////////////////////////////////////////
     330unsigned int _get_current_context_slot(unsigned int slot_id)
     331{
     332    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
     333    unsigned int                        current = _physical_read_access( &(psched->current) );
     334    return _physical_read_access( &(psched->context[current][slot_id]) );
     335}
     336/////////////////////////////////////////////i//////////////////////////////////
     337//    _get_interrupt_vector_entry()
     338// This function returns the interrupt_vector entry defined by argument index.
     339////////////////////////////////////////////////////////////////////////////////
     340unsigned int _get_interrupt_vector_entry( unsigned int index )
     341{
     342    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
     343    return _physical_read_access( &(psched->interrupt_vector[index]) );
     344}
     345////////////////////////////////////////////////////////////////////////////
     346//    _set_current_task_id()
     347// This function returns the index of the currently running task.
     348////////////////////////////////////////////////////////////////////////////
     349void _set_current_task_id( unsigned int value )
     350{
     351    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
     352    _physical_write_access( &(psched->current), value );
    229353}
    230354
     
    283407}
    284408
    285 
  • soft/giet_vm/sys/common.h

    r166 r189  
    3232///////////////////////////////////////////////////////////////////////////////////
    3333
    34 void _puts(char *string);
    35 void _putw(unsigned int val);
     34void                            _puts(char *string);
     35void                            _putw(unsigned int val);
     36void                            _putd(unsigned int val);
    3637
    37 unsigned int _strncmp(const char* s1, const char* s2, unsigned int n);
     38unsigned int            _strncmp(const char* s1, const char* s2, unsigned int n);
    3839
    39 void _dcache_buf_invalidate(const void *buffer, unsigned int size);
     40void                            _dcache_buf_invalidate(const void *buffer, unsigned int size);
    4041
    41 void _itoa_dec(unsigned int val, char* buf);
    42 void _itoa_hex(unsigned int val, char* buf);
     42void                            _itoa_dec(unsigned int val, char* buf);
     43void                            _itoa_hex(unsigned int val, char* buf);
    4344
    44 unsigned int _get_epc();
    45 unsigned int _get_ptpr();
    46 unsigned int _get_bar();
    47 unsigned int _get_cr();
     45void                            _dtlb_off(void);
     46void                            _dtlb_on(void);
    4847
    49 void _get_lock(unsigned int* lock);
    50 void _release_lock(unsigned int* lock);
     48void                            _it_mask(void);
     49void                            _it_enable(void);
     50
     51unsigned int            _get_epc(void);
     52unsigned int            _get_ptpr(void);
     53unsigned int            _get_bvar(void);
     54unsigned int            _get_cr(void);
     55unsigned int            _get_sched(void);
     56
     57unsigned int            _get_current_context_slot(unsigned int index);
     58unsigned int            _get_interrupt_vector_entry(unsigned int index);
     59unsigned int            _get_current_task_id(void);
     60unsigned int            _get_tasks_number(void);
     61
     62void                            _set_current_task_id( unsigned int value);
     63
     64void                            _get_lock(unsigned int* lock);
     65void                            _release_lock(unsigned int* lock);
    5166
    5267mapping_cluster_t*  _get_cluster_base( mapping_header_t* header );
  • soft/giet_vm/sys/ctx_handler.c

    r167 r189  
    1 ///////////////////////////////////////////////////////////////////////////////////
     1///////////////////////////////////////////////////////////////////////////////////////
    22// File     : ctx_handler.c
    33// Date     : 01/04/2012
    44// Authors  : alain greiner & joel porquet
    55// Copyright (c) UPMC-LIP6
    6 ////////////////////////////////////////////////////////////////////////////////////
    7 // The ctx_handler.h and ctx_handler.c files are part of the GIET nano-kernel.
     6///////////////////////////////////////////////////////////////////////////////////////
     7// The ctx_handler.h and ctx_handler.c files are part of the GIET-VM nano-kernel.
    88// This code is used to support context switch when several tasks are executing
    99// in time multiplexing on a single processor.
    1010// The tasks must be statically allocated to a processor in the boot phase, and
    11 // there is one private scheduler per processor:  NB_CLUSTERS * NB_PROCS
    12 // Each sheduler contains up to NB_TASKS_MAX contexts.
    13 ////////////////////////////////////////////////////////////////////////////////////
    14 // A task context is an array of 64 words = 256 bytes.
    15 // It contains copies of processor registers, when the task is not running,
    16 // and some general informations associated to the task.
    17 //
    18 // - It contains GPR[i], generally stored in slot (i). $0, *26 & $27 are not saved.
    19 // - It contains HI & LO registers.
    20 // - It contains CP0 registers: EPC, SR, CR.
    21 // - It contains CP2 registers : PTPR and MODE.
    22 // - It contains the TTY global index, the FBDMA global index, the virtual base
    23 //   address of the page table (PTAB), and the task global index (TASK).
    24 //
    25 // ctx[0]<- SR|ctx[8] <- $8 |ctx[16]<- $16|ctx[24]<- $24|ctx[32]<- EPC |ctx[40]<- TTY
    26 // ctx[1]<- $1|ctx[9] <- $9 |ctx[17]<- $17|ctx[25]<- $25|ctx[33]<- CR  |ctx[41]<- FBDMA
    27 // ctx[2]<- $2|ctx[10]<- $10|ctx[18]<- $18|ctx[26]<- LO |ctx[34]<- *** |ctx[42]<- PTAB
    28 // ctx[3]<- $3|ctx[11]<- $11|ctx[19]<- $19|ctx[27]<- HI |ctx[35]<- PTPR|ctx[43]<- TASK
    29 // ctx[4]<- $4|ctx[12]<- $12|ctx[20]<- $20|ctx[28]<- $28|ctx[36]<- MODE|ctx[44]<- ***
    30 // ctx[5]<- $5|ctx[13]<- $13|ctx[21]<- $21|ctx[29]<- SP |ctx[37]<- *** |ctx[45]<- ***
    31 // ctx[6]<- $6|ctx[14]<- $14|ctx[22]<- $22|ctx[30]<- $30|ctx[38]<- *** |ctx[46]<- ***
    32 // ctx[7]<- $7|ctx[15]<- $15|ctx[23]<- $23|ctx[31]<- RA |ctx[39]<- *** |ctx[47]<- ***
    33 /////////////////////////////////////////////////////////////////////////////////////
     11// there is one private scheduler per processor.
     12// Each sheduler contains up to 15 task contexts.
     13///////////////////////////////////////////////////////////////////////////////////////
    3414
    3515#include <giet_config.h>
     
    4020#include <sys_handler.h>
    4121
    42 extern void _task_switch(unsigned int *, unsigned int *);
    43 
    44 /////////////////////////////////////////////////////////////////////////////////
    45 //      Global variables : array of schedulers (one scheduler per processor)
    46 /////////////////////////////////////////////////////////////////////////////////
    47 
    48 __attribute__((section (".kdata"))) static_scheduler_t _scheduler[NB_CLUSTERS * NB_PROCS];
     22///////////////////////////////////////////////////////////////////////////////////////
     23// A task context is an array of 64 words = 256 bytes.
     24// It contains copies of processor registers (when the task is preempted),
     25// and some general informations associated to the task.
     26//
     27// - It contains GPR[i], generally stored in slot (i). $0, *26 & $27 are not saved.
     28// - It contains HI & LO registers.
     29// - It contains CP0 registers: EPC, SR, CR, SCHED
     30// - It contains CP2 registers : PTPR and MODE.
     31// - It contains TTY global index, the FBDMA global index, the virtual base
     32//   address of the page table (PTAB), and the task global index (TASK).
     33//
     34// ctx[0]<- SR|ctx[8] <- $8 |ctx[16]<- $16|ctx[24]<- $24|ctx[32]<- EPC |ctx[40]<- TTY
     35// ctx[1]<- $1|ctx[9] <- $9 |ctx[17]<- $17|ctx[25]<- $25|ctx[33]<- CR  |ctx[41]<- FBDMA
     36// ctx[2]<- $2|ctx[10]<- $10|ctx[18]<- $18|ctx[26]<- LO |ctx[34]<- *** |ctx[42]<- PTAB
     37// ctx[3]<- $3|ctx[11]<- $11|ctx[19]<- $19|ctx[27]<- HI |ctx[35]<- PTPR|ctx[43]<- TASK
     38// ctx[4]<- $4|ctx[12]<- $12|ctx[20]<- $20|ctx[28]<- $28|ctx[36]<- MODE|ctx[44]<- SCHED
     39// ctx[5]<- $5|ctx[13]<- $13|ctx[21]<- $21|ctx[29]<- SP |ctx[37]<- *** |ctx[45]<- TIMER
     40// ctx[6]<- $6|ctx[14]<- $14|ctx[22]<- $22|ctx[30]<- $30|ctx[38]<- *** |ctx[46]<- ***
     41// ctx[7]<- $7|ctx[15]<- $15|ctx[23]<- $23|ctx[31]<- RA |ctx[39]<- *** |ctx[47]<- ***
     42////////////////////////////////////////////////////////////////////////////////////////
     43
     44extern void _task_switch(unsigned int*, unsigned int*);
    4945
    5046/////////////////////////////////////////////////////////////////////////////////
     
    5248// This function performs a context switch between the running task
    5349// and  another task, using a round-robin sheduling policy.
    54 // It use the global variable scheduler[] : array indexed by the procid,
    55 // that contains NB_CLUSTERS * NB_PROCS entries.
    56 // The return address contained in $31 is saved in the _current task context
     50//
     51// It desactivate the DTLB, to directly access the scheduler using
     52// the physical address stored in register CP0_SCHED.
     53// All the context switch procedure is executed with interrupts masked.
     54//
     55// The return address contained in $31 is saved in the current task context
    5756// (in the ctx[31] slot), and the function actually returns to the address
    58 // contained in the ctx[31] slot of the new task context. To perform the
    59 // actual switch, it calls the _task_switch function written in assembly language.
     57// contained in the ctx[31] slot of the next task context.
    6058/////////////////////////////////////////////////////////////////////////////////
    6159void _ctx_switch()
    6260{
    63     unsigned char curr_task_id;
    64     unsigned char next_task_id;
    65 
    66     unsigned int *curr_context;
    67     unsigned int *next_context;
    68 
    69     unsigned int proc_id   = _procid();
    70     unsigned int tasks     = _scheduler[proc_id].tasks;
    71 
    72     // return if only one task  */
    73     if ( tasks <= 1) return;
    74  
    75     // compute the task context base address for the current task
    76     curr_task_id = _scheduler[proc_id].current;
    77     curr_context = &(_scheduler[proc_id].context[curr_task_id][0]);
     61    unsigned int                        tasks;
     62    unsigned int                        curr_task_id;
     63    unsigned int                        next_task_id;
     64    unsigned int                        *curr_ctx_paddr;
     65    unsigned int                        *next_ctx_paddr;
     66
     67    // get scheduler physical address
     68    static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
     69
     70    // get number of tasks allocated to scheduler
     71    tasks = _get_tasks_number();
     72
     73    // no switch if only one task
     74    if ( tasks > 1)
     75    {
     76        // compute the context physical address for the current task
     77        curr_task_id = _get_current_task_id();
     78        curr_ctx_paddr = &(psched->context[curr_task_id][0]);
    7879   
    79     // select the next task using a round-robin scheduling policy
    80     next_task_id = (curr_task_id + 1) % tasks;
     80        // select the next task using a round-robin policy
     81        next_task_id = (curr_task_id + 1) % tasks;
    8182   
    82     // compute the task context base address for the next task
    83     next_context = &(_scheduler[proc_id].context[next_task_id][0]);
     83        // compute the context physical address for the next task
     84        next_ctx_paddr = &(psched->context[next_task_id][0]);
     85
     86        // update the scheduler state
     87        _set_current_task_id( next_task_id );
    8488
    8589#if GIET_DEBUG_SWITCH
    8690_get_lock( &_tty_put_lock );
    8791_puts( "\n[GIET] Context switch for processor ");
    88 _putw( proc_id );
     92_putw( _procid() );
    8993_puts( " at cycle ");
    9094_putw( _proctime() );
     
    102106#endif
    103107
    104     //  update the scheduler state, and makes the task switch
    105     _scheduler[proc_id].current = next_task_id;
    106     _task_switch( curr_context, next_context );
    107 
     108        // makes the task switch
     109        _task_switch( curr_ctx_paddr, next_ctx_paddr );
     110
     111/*
     112        asm volatile( "ori              $27,    $0,             0xB     \n"
     113                      "mtc2             $27,    $1                      \n"             // desactivate DTLB
     114
     115                      "add      $27,    %0,     $0  \n"         // $27 <= &curr_ctx
     116
     117                      "mfc0     $26,    $12         \n"         // $26 <= SR
     118                      "sw       $26,    0*4($27)    \n"         // ctx[0] <= SR
     119                      ".set noat                    \n"
     120                      "sw       $1,     1*4($27)    \n"         // ctx[1] <= $1
     121                      ".set at                      \n"
     122                      "sw       $2,     2*4($27)    \n"         // ctx[2] <= $2
     123                      "sw       $3,     3*4($27)    \n"         // ctx[3] <= $3
     124                      "sw       $4,     4*4($27)    \n"         // ctx[4] <= $4
     125                      "sw       $5,     5*4($27)    \n"         // ctx[5] <= $5
     126                      "sw       $6,     6*4($27)    \n"         // ctx[6] <= $6
     127                      "sw       $7,     7*4($27)    \n"         // ctx[7] <= $7
     128                      "sw       $8,     8*4($27)    \n"         // ctx[8] <= $8
     129                      "sw       $9,     9*4($27)    \n"         // ctx[9] <= $9
     130                      "sw       $10,    10*4($27)   \n"         // ctx[10] <= $10
     131                      "sw       $11,    11*4($27)   \n"         // ctx[11] <= $11
     132                      "sw       $12,    12*4($27)   \n"         // ctx[12] <= $12
     133                      "sw       $13,    13*4($27)   \n"         // ctx[13] <= $13
     134                      "sw       $14,    14*4($27)   \n"         // ctx[14] <= $14
     135                      "sw       $15,    15*4($27)   \n"         // ctx[15] <= $15
     136                      "sw       $16,    16*4($27)   \n"         // ctx[16] <= $16
     137                      "sw       $17,    17*4($27)   \n"         // ctx[17] <= $17
     138                      "sw       $18,    18*4($27)   \n"         // ctx[18] <= $18
     139                      "sw       $19,    19*4($27)   \n"         // ctx[19] <= $19
     140                      "sw       $20,    20*4($27)   \n"         // ctx[20] <= $20
     141                      "sw       $21,    21*4($27)   \n"         // ctx[21] <= $21
     142                      "sw       $22,    22*4($27)   \n"         // ctx[22] <= $22
     143                      "sw       $23,    23*4($27)   \n"         // ctx[23] <= $23
     144                      "sw       $24,    24*4($27)   \n"         // ctx[24] <= $24
     145                      "sw       $25,    25*4($27)   \n"         // ctx[25] <= $25
     146                      "mflo     $26                 \n"
     147                      "sw       $26,    26*4($27)   \n"         // ctx[26] <= LO
     148                      "mfhi     $26                 \n"
     149                      "sw       $26,    27*4($27)   \n"         // ctx[27] <= H1
     150                      "sw       $28,    28*4($27)   \n"         // ctx[28] <= $28
     151                      "sw       $29,    29*4($27)   \n"         // ctx[29] <= $29
     152                      "sw       $30,    30*4($27)   \n"         // ctx[30] <= $30
     153                      "sw       $31,    31*4($27)   \n"         // ctx[31] <= $31
     154                      "mfc0     $26,    $14         \n"
     155                      "sw       $26,    32*4($27)   \n"         // ctx[32] <= EPC
     156                      "mfc0     $26,    $13         \n"
     157                      "sw       $26,    33*4($27)   \n"         // ctx[33] <= CR
     158                      "mfc2     $26,    $0          \n"
     159                      "sw       $26,    35*4($27)   \n"         // ctx[35] <= PTPR
     160
     161                      "add      $27,    %1,     $0      \n"             // $27<= &next_ctx
     162
     163                      "lw       $26,    35*4($27)       \n"
     164                      "mtc2     $26,    $0          \n"         // restore PTPR
     165                      "lw       $26,    0*4($27)        \n"
     166                      "mtc0     $26,    $12                     \n"             // restore SR
     167                      ".set noat                    \n"
     168                      "lw       $1,     1*4($27)        \n"             // restore $1
     169                      ".set at                      \n"
     170                          "lw       $2,     2*4($27)    \n"             // restore $2
     171                      "lw       $3,     3*4($27)    \n"         // restore $3
     172                      "lw       $4,     4*4($27)    \n"         // restore $4
     173                      "lw       $5,     5*4($27)    \n"         // restore $5
     174                      "lw       $6,     6*4($27)    \n"         // restore $6
     175                      "lw       $7,     7*4($27)    \n"         // restore $7
     176                      "lw       $8,     8*4($27)    \n"         // restore $8
     177                      "lw       $9,     9*4($27)    \n"         // restore $9
     178                      "lw       $10,    10*4($27)   \n"         // restore $10
     179                      "lw       $11,    11*4($27)   \n"         // restore $11
     180                      "lw       $12,    12*4($27)   \n"         // restore $12
     181                      "lw       $13,    13*4($27)   \n"         // restore $13
     182                      "lw       $14,    14*4($27)   \n"         // restore $14
     183                      "lw       $15,    15*4($27)   \n"         // restore $15
     184                      "lw       $16,    16*4($27)   \n"         // restore $16
     185                      "lw       $17,    17*4($27)   \n"         // restore $17
     186                      "lw       $18,    18*4($27)   \n"         // restore $18
     187                      "lw       $19,    19*4($27)   \n"         // restore $19
     188                      "lw       $20,    20*4($27)   \n"         // restore $20
     189                      "lw       $21,    21*4($27)   \n"         // restore $21
     190                      "lw       $22,    22*4($27)   \n"         // restore $22
     191                      "lw       $23,    23*4($27)   \n"         // restore $23
     192                      "lw       $24,    24*4($27)   \n"         // restore $24
     193                      "lw       $25,    25*4($27)   \n"         // restore $25
     194                      "lw       $26,    26*4($27)   \n"
     195                      "mtlo     $26                 \n"         // restore LO
     196                      "lw       $26,    27*4($27)   \n"
     197                      "mthi     $26                 \n"         // restore HI
     198                      "lw       $28,    28*4($27)   \n"         // restore $28
     199                      "lw       $29,    29*4($27)   \n"         // restore $29
     200                      "lw       $30,    30*4($27)   \n"         // restore $30
     201                      "lw       $31,    31*4($27)   \n"         // restore $31
     202                      "lw       $26,    32*4($27)   \n"
     203                      "mtc0     $26,    $14         \n"         // restore EPC
     204                      "lw       $26,    33*4($27)   \n"
     205                      "mtc0     $26,    $13         \n"         // restore CR
     206
     207                      "ori              $27,    $0,             0xF \n"
     208                      "mtc2             $27,    $1          \n"         // activate DTLB
     209                      :
     210                      : "r"(curr_ctx_paddr), "r"(next_ctx_paddr)
     211                      : "$1" ,            "$4" ,"$5" ,"$6" ,"$7" ,"$8" ,"$9" ,"$10",
     212                        "$11","$12","$13","$14","$15","$16","$17","$18","$19","$20",
     213                        "$21","$22","$23","$24","$25","$26","$27",      "$29",
     214                        "$31" );
     215*/
     216    }
    108217} // end _ctx_switch
    109218
  • soft/giet_vm/sys/ctx_handler.h

    r167 r189  
    1010typedef struct static_scheduler_s
    1111{
    12     unsigned int        context[GIET_NB_TASKS_MAX][64];   // task contexts
    13     unsigned int        tasks;                                        // actual number of tasks
    14     unsigned int        current;                                      // current task index
     12    unsigned int        context[15][64];                // at most 15 task contexts
     13    unsigned int        tasks;                                  // actual number of tasks
     14    unsigned int        current;                                // current task index
     15    unsigned int        interrupt_vector[32];   // interrupt vector
    1516} static_scheduler_t;
    1617
     
    3233#define CTX_PTAB_ID             42
    3334#define CTX_TASK_ID             43
    34 
     35#define CTX_SCHED_ID    44
     36#define CTX_TIMER_ID    45
    3537
    3638//////////////////////////////////////////////////////////////////////////////////
  • soft/giet_vm/sys/drivers.c

    r169 r189  
    55// Copyright (c) UPMC-LIP6
    66///////////////////////////////////////////////////////////////////////////////////
    7 // The drivers.c and drivers.h files are part ot the GIET nano kernel.
     7// The drivers.c and drivers.h files are part ot the GIET-VM nano kernel.
    88// They contains the drivers for the peripherals available in the SoCLib library:
    99// - vci_multi_tty
     
    1111// - vci_multi_dma
    1212// - vci_multi_icu
     13// - vci_xicu
    1314// - vci_gcd
    1415// - vci_frame_buffer
     
    1617//
    1718// The following global parameters must be defined in the giet_config.h file:
    18 // - NB_CLUSTERS  : number of clusters
    19 // - NB_PROCS     : number of PROCS per cluster
    20 // - NB_TIMERS    : number of TIMERS per cluster
    21 // - NB_DMAS      : number of DMA channels
    22 // - NB_TTYS      : number of TTY terminals
    23 // - NB_TIMERS    : number of TIMERS per cluster
    24 // - CLUSTER_SPAN : address increment between clusters
     19// - NB_CLUSTERS   
     20// - NB_PROCS_MAX 
     21// - NB_TIMERS_MAX   
     22// - NB_DMAS_MAX     
     23// - NB_TTYS   
    2524//
    2625// The following base addresses must be defined in the sys.ld file:
     
    4342#include <ctx_handler.h>
    4443
    45 #if !defined(NB_PROCS)
    46 # error: You must define NB_PROCS in 'giet_config.h' file!
    47 #endif
    4844#if !defined(NB_CLUSTERS)
    49 # error: You must define NB_CLUSTERS in 'giet_config.h' file!
    50 #endif
     45# error: You must define NB_CLUSTERS in 'giet_config.h' file
     46#endif
     47
     48#if !defined(NB_PROCS_MAX)
     49# error: You must define NB_PROCS_MAX in 'giet_config.h' file
     50#endif
     51
     52#if (NB_PROCS_MAX > 8)
     53# error: NB_PROCS_MAX cannot be larger than 8!
     54#endif
     55
    5156#if !defined(CLUSTER_SPAN)
    52 # error: You must define CLUSTER_SPAN in 'giet_config.h' file!
    53 #endif
     57# error: You must define CLUSTER_SPAN in 'giet_config.h' file
     58#endif
     59
    5460#if !defined(NB_TTYS)
    55 # error: You must define NB_TTYS in 'giet_config.h' file!
    56 #endif
    57 #if !defined(NB_DMAS)
    58 # error: You must define NB_DMAS in 'giet_config.h' file!
    59 #endif
    60 #if !defined(NB_TIMERS)
    61 # error: You must define NB_TIMERS in 'giet_config.h' file!
     61# error: You must define NB_TTYS in 'giet_config.h' file
    6262#endif
    6363
     
    6666#endif
    6767
    68 #if (NB_TIMERS < NB_PROCS)
    69 # error: NB_TIMERS must be larger or equal to NB_PROCS!
    70 #endif
    71 
    72 #if (NB_PROCS > 8)
    73 # error: NB_PROCS cannot be larger than 8!
    74 #endif
    75 
    76 #if (NB_DMAS < 1)
    77 # error: NB_DMAS cannot be 0!
    78 #endif
    79 
    80 
    81 /////////////////////////////////////////////////////////////////////////////
    82 //      Global (uncachable) variables
    83 /////////////////////////////////////////////////////////////////////////////
     68#if !defined(NB_DMAS_MAX)
     69# error: You must define NB_DMAS_MAX in 'giet_config.h' file
     70#endif
     71
     72#if (NB_DMAS_MAX < 1)
     73# error: NB_DMAS_MAX cannot be 0!
     74#endif
     75
     76#if !defined(NB_TIMERS_MAX)
     77# error: You must define NB_TIMERS_MAX in 'giet_config.h' file
     78#endif
     79
     80#if ( (NB_TIMERS_MAX + NB_PROCS_MAX) > 32 )
     81# error: NB_TIMERS_MAX + NB_PROCS_MAX cannot be larger than 32
     82#endif
     83
     84#if !defined(NB_IOCS)
     85# error: You must define NB_IOCS in 'giet_config.h' file
     86#endif
     87
     88#if ( NB_IOCS > 1 )
     89# error: NB_IOCS cannot be larger than 1
     90#endif
     91
    8492
    8593#define in_unckdata __attribute__((section (".unckdata")))
    8694
    87 // IOC variables
    88 in_unckdata volatile unsigned char _ioc_status       = 0;
    89 in_unckdata volatile unsigned char _ioc_done         = 0;
    90 in_unckdata unsigned int                   _ioc_lock         = 0;
    91 in_unckdata unsigned int                   _ioc_iommu_ix1    = 0;
    92 in_unckdata unsigned int                   _ioc_iommu_npages;
    93 
    94 // DMA variables
    95 in_unckdata volatile unsigned int  _dma_status[NB_DMAS];
    96 in_unckdata volatile unsigned char _dma_busy[NB_DMAS] = { [0 ... NB_DMAS-1] = 0 };
    97 in_unckdata volatile unsigned char _dma_iommu_ix1     = 1;
    98 in_unckdata volatile unsigned char _dma_iommu_npages[NB_DMAS];
     95
     96//////////////////////////////////////////////////////////////////////////////
     97//      VciMultiTimer driver
     98//////////////////////////////////////////////////////////////////////////////
     99// There is one multi_timer (or xicu) component per cluster.
     100// The global index is cluster_id*(NB_PROCS_MAX+NB_TIMERS_MAX) + local_id
     101// There is two types of timers:
     102// - "system" timers : one per processor, used for context switch.
     103//   local_id in [0, NB_PROCS_MAX-1],
     104// - "user" timers : requested by the task in the mapping_info data structure.
     105//   local_id in [NB_PROC_MAX, NB_PROCS_MAX+NB_TIMERS_MAX-1],
     106//   For each user timer, the tty_id is stored in the context of the task
     107//   and must be explicitely defined in the boot code.
     108// These timers can be implemented in a vci_multi_timer component
     109// or in a vci_xicu component (depending on the GIET_USE_XICU parameter).
     110//////////////////////////////////////////////////////////////////////////////
     111
     112// User Timer signaling variables
     113
     114#if (NB_TIMERS_MAX > 0)
     115in_unckdata volatile unsigned char _user_timer_event[NB_CLUSTERS*NB_TIMERS_MAX]
     116         = { [0 ... ((NB_CLUSTERS*NB_TIMERS_MAX)-1)] = 0 };
     117#endif
     118
     119//////////////////////////////////////////////////////////////////////////////
     120//     _timer_access()
     121// This function is the only way to access a timer device.
     122// It can be a multi-timer component or an xicu component.
     123// It can be used by the kernel to initialise a "system" timer,
     124// or by a task (through a system call) to configure an "user" timer.
     125// Returns 0 if success, > 0 if error.
     126//////////////////////////////////////////////////////////////////////////////
     127unsigned int _timer_access( unsigned int        read,
     128                            unsigned int        cluster_id,
     129                            unsigned int        local_id,
     130                            unsigned int        register_id,
     131                            unsigned int*       buffer )
     132{
     133    // parameters checking
     134    if ( register_id >= TIMER_SPAN)                                     return 1;
     135    if ( cluster_id >= NB_CLUSTERS)                                     return 1;
     136    if ( local_id >= NB_TIMERS_MAX + NB_PROCS_MAX ) return 1;
     137
     138#if GIET_USE_XICU
     139
     140    unsigned int* timer_address = //TODO
     141
     142#else
     143
     144    unsigned int* timer_address = (unsigned int*)&seg_timer_base +
     145                                  (cluster_id * CLUSTER_SPAN)  +
     146                                  (local_id * TIMER_SPAN);
     147#endif
     148
     149    if (read)   *buffer = timer_address[register_id]; // read word
     150    else                timer_address[register_id] = *buffer; // write word
     151    return 0;
     152}
     153//////////////////////////////////////////////////////////////////////////////
     154//     _timer_write()
     155// This function implements a write access to a "user" timer register.
     156// It gets the cluster_id and local_id from the global index stored in
     157// the task context and use the timer_access() function to make the write.
     158// Returns 0 if success, > 0 if error.
     159//////////////////////////////////////////////////////////////////////////////
     160unsigned int _timer_write( unsigned int register_id,
     161                           unsigned int value )
     162{
     163    unsigned int buffer     = value;
     164    unsigned int timer_id   = _get_current_context_slot(CTX_TIMER_ID);
     165    unsigned int cluster_id = timer_id / (NB_PROCS_MAX + NB_TIMERS_MAX);
     166    unsigned int local_id   = timer_id % (NB_PROCS_MAX + NB_TIMERS_MAX);
     167
     168    // checking user timer
     169    if ( local_id < NB_PROCS_MAX )
     170    {
     171        return 2;
     172    }
     173    else
     174    {
     175        return _timer_access ( 0,                               // write access
     176                               cluster_id,
     177                               local_id,
     178                               register_id,
     179                               &buffer );
     180    }
     181}
     182//////////////////////////////////////////////////////////////////////////////
     183//     _timer_read()
     184// This function implements a read access to a "user" timer register.
     185// It gets the cluster_id and local_id from the global index stored in
     186// the task context and use the timer_access() function to make the read.
     187// Returns 0 if success, > 0 if error.
     188//////////////////////////////////////////////////////////////////////////////
     189unsigned int _timer_read( unsigned int  register_id,
     190                          unsigned int* buffer )
     191{
     192    unsigned int timer_id   = _get_current_context_slot(CTX_TIMER_ID);
     193    unsigned int cluster_id = timer_id / (NB_PROCS_MAX + NB_TIMERS_MAX);
     194    unsigned int local_id   = timer_id % (NB_PROCS_MAX + NB_TIMERS_MAX);
     195
     196    // checking user timer
     197    if ( local_id < NB_PROCS_MAX )
     198    {
     199        return 2;
     200    }
     201    else
     202    {
     203        return _timer_access ( 1,                               // read access
     204                               cluster_id,
     205                               local_id,
     206                               register_id,
     207                               buffer );
     208    }
     209}
     210/////////////////////////////////////////////////////////////////////////////////
     211//     _timer_check()
     212/////////////////////////////////////////////////////////////////////////////////
     213
     214/////////////////////////////////////////////////////////////////////////////////
     215//      VciMultiTty driver
     216/////////////////////////////////////////////////////////////////////////////////
     217// There is only one multi_tty controler in the architecture.
     218// The total number of TTYs is defined by the configuration parameter NB_TTYS.
     219// The "system" terminal is TTY[0].
     220// The "user" TTYs are allocated to applications by the GIET in the boot phase,
     221// as defined in the mapping_info data structure. The corresponding tty_id must
     222// be stored in the context of the task by the boot code.
     223// The TTY address is : seg_tty_base + tty_id*TTY_SPAN
     224/////////////////////////////////////////////////////////////////////////////////
    99225
    100226// TTY variables
    101227in_unckdata volatile unsigned char _tty_get_buf[NB_TTYS];
    102228in_unckdata volatile unsigned char _tty_get_full[NB_TTYS] = { [0 ... NB_TTYS-1] = 0 };
    103 in_unckdata unsigned int           _tty_put_lock          = 0;
    104 
    105 //////////////////////////////////////////////////////////////////////////////
    106 //      VciMultiTimer driver
    107 //////////////////////////////////////////////////////////////////////////////
    108 // There is one MULTI-TIMER component per cluster.
    109 // The number of timers per cluster must be larger or equal to the number
    110 // processors (NB_TIMERS >= NB_PROCS), because each processor uses a private
    111 // yimer for context switch.
    112 // The total number of timers is NB_CLUSTERS * NB_TIMERS
    113 // The global timer index = cluster_id*NB_TIMERS + timer_id
    114 //////////////////////////////////////////////////////////////////////////////
    115 
    116 //////////////////////////////////////////////////////////////////////////////
    117 // _timer_write()
    118 //
    119 // Write a 32-bit word in a memory mapped register of a timer device,
    120 // identified by the cluster index and the local timer index.
    121 // Returns 0 if success, > 0 if error.
    122 //////////////////////////////////////////////////////////////////////////////
    123 unsigned int _timer_write( unsigned int cluster_index,
    124                            unsigned int timer_index,
    125                            unsigned int register_index,
    126                            unsigned int value )
    127 {
    128     unsigned int*       timer_address;
    129 
    130     // parameters checking
    131     if ( register_index >= TIMER_SPAN)          return 1;
    132     if ( cluster_index >= NB_CLUSTERS)          return 1;
    133     if ( timer_index >= NB_TIMERS )         return 1;
    134 
    135     timer_address = (unsigned int*)&seg_timer_base +
    136                     ( cluster_index * CLUSTER_SPAN )  +
    137                     ( timer_index * TIMER_SPAN );
    138 
    139     timer_address[register_index] = value; // write word
    140 
    141     return 0;
    142 }
    143 
    144 //////////////////////////////////////////////////////////////////////////////
    145 // _timer_read()
    146 //
    147 // Read a 32-bit word in a memory mapped register of a timer device,
    148 // identified by the cluster index and the local timer index.
    149 // Returns 0 if success, > 0 if error.
    150 //////////////////////////////////////////////////////////////////////////////
    151 unsigned int _timer_read(unsigned int cluster_index,
    152                          unsigned int timer_index,
    153                          unsigned int register_index,
    154                          unsigned int *buffer)
    155 {
    156     unsigned int *timer_address;
    157 
    158     // parameters checking
    159     if ( register_index >= TIMER_SPAN)          return 1;
    160     if ( cluster_index >= NB_CLUSTERS)          return 1;
    161     if ( timer_index >= NB_TIMERS )         return 1;
    162 
    163     timer_address = (unsigned int*)&seg_timer_base +
    164                     ( cluster_index * CLUSTER_SPAN )  +
    165                     ( timer_index * TIMER_SPAN );
    166 
    167     *buffer = timer_address[register_index]; // read word
    168 
    169     return 0;
    170 }
    171 
     229in_unckdata unsigned int           _tty_put_lock = 0;  // protect kernel TTY[0]
     230
     231////////////////////////////////////////////////////////////////////////////////
     232//      _tty_error()
     233////////////////////////////////////////////////////////////////////////////////
     234void _tty_error()
     235{
     236    unsigned int task_id = _get_current_task_id();
     237    unsigned int proc_id = _procid();
     238
     239    _get_lock(&_tty_put_lock);
     240    _puts("\n[GIET ERROR] TTY index too large for task ");
     241    _putw( task_id );
     242    _puts(" on processor ");
     243    _putw( proc_id );
     244    _puts("\n");
     245    _release_lock(&_tty_put_lock);
     246}
    172247/////////////////////////////////////////////////////////////////////////////////
    173 //      VciMultiTty driver
    174 /////////////////////////////////////////////////////////////////////////////////
    175 // The total number of TTYs is defined by the configuration parameter NB_TTYS.
    176 // The system terminal is TTY[0].
    177 // The TTYs are allocated to applications by the GIET in the boot phase.
    178 // The nummber of TTYs allocated to each application, and used by each
    179 // task can be defined in the mapping_info data structure.
    180 // For each user task, the tty_id is stored in the context of the task (slot 34),
    181 // and must be explicitely defined in the boot code.
    182 // The TTY address is always computed as : seg_tty_base + tty_id*TTY_SPAN
    183 ///////////////////////////////////////////////////////////////////////////////////
    184 
    185 //////////////////////////////////////////////////////////////////////////////
    186 // _tty_write()
    187 //
     248//      _tty_write()
    188249// Write one or several characters directly from a fixed-length user buffer to
    189250// the TTY_WRITE register of the TTY controler.
     
    192253// the transfer as soon as the TTY_STATUS[WRITE] bit is set.
    193254// The function returns  the number of characters that have been written.
    194 //////////////////////////////////////////////////////////////////////////////
     255/////////////////////////////////////////////////////////////////////////////////
    195256unsigned int _tty_write( const char             *buffer,
    196257                         unsigned int   length)
    197258{
    198     volatile unsigned int *tty_address;
    199 
    200     unsigned int proc_id;
    201     unsigned int task_id;
    202     unsigned int tty_id;
    203     unsigned int nwritten;
    204 
    205     proc_id = _procid();
    206    
    207     task_id = _scheduler[proc_id].current;
    208     tty_id  = _scheduler[proc_id].context[task_id][CTX_TTY_ID];
    209 
    210     tty_address = (unsigned int*)&seg_tty_base + tty_id*TTY_SPAN;
     259    unsigned int        nwritten;
     260
     261    unsigned int        tty_id = _get_current_context_slot(CTX_TTY_ID);
     262    if ( tty_id >= NB_TTYS )
     263    {
     264        _tty_error();
     265        return 0;
     266    }
     267
     268    unsigned int*       tty_address = (unsigned int*)&seg_tty_base + tty_id*TTY_SPAN;
    211269
    212270    for (nwritten = 0; nwritten < length; nwritten++)
     
    221279    return nwritten;
    222280}
    223 
    224281//////////////////////////////////////////////////////////////////////////////
    225 // _tty_read_irq()
    226 //
     282//      _tty_read_irq()
    227283// This non-blocking function uses the TTY_GET_IRQ[tty_id] interrupt and
    228284// the associated kernel buffer, that has been written by the ISR.
     
    235291                            unsigned int        length)
    236292{
    237     unsigned int proc_id;
    238     unsigned int task_id;
    239     unsigned int tty_id;
    240     unsigned int ret;
    241 
    242     proc_id = _procid();
    243     task_id = _scheduler[proc_id].current;
    244     tty_id  = _scheduler[proc_id].context[task_id][CTX_TTY_ID];
     293    unsigned int        tty_id = _get_current_context_slot(CTX_TTY_ID);
     294
     295    if ( tty_id >= NB_TTYS )
     296    {
     297        _tty_error();
     298        return 0;
     299    }
    245300
    246301    if (_tty_get_full[tty_id] == 0)
    247302    {
    248         ret = 0;
     303        return 0;
    249304    }
    250305    else
     
    252307        *buffer = _tty_get_buf[tty_id];
    253308        _tty_get_full[tty_id] = 0;
    254         ret = 1;
    255     }
    256     return ret;
    257 }
    258 
    259 ////////////////////////////////////////////////////////////////////////////////
    260 // _tty_read()
    261 //
     309        return 1;
     310    }
     311}
     312////////////////////////////////////////////////////////////////////////////////
     313//     _tty_read()
    262314// This non-blocking function fetches one character directly from the TTY_READ
    263315// register of the TTY controler, and writes this character to the user buffer.
     
    268320                        unsigned int    length)
    269321{
    270     volatile unsigned int *tty_address;
    271 
    272     unsigned int proc_id;
    273     unsigned int task_id;
    274     unsigned int tty_id;
    275 
    276     proc_id = _procid();
    277     task_id = _scheduler[proc_id].current;
    278     tty_id  = _scheduler[proc_id].context[task_id][CTX_TTY_ID];
    279 
    280     tty_address = (unsigned int*)&seg_tty_base + tty_id*TTY_SPAN;
    281 
    282     if ((tty_address[TTY_STATUS] & 0x1) != 0x1) return 0;
    283 
    284     *buffer = (char)tty_address[TTY_READ];
    285     return 1;
    286 }
    287 
    288 ////////////////////////////////////////////////////////////////////////////////
    289 //      VciMultiIcu driver
    290 ////////////////////////////////////////////////////////////////////////////////
    291 // There is in principle one MULTI-ICU component per cluster, and the
    292 // number of independant ICUs is equal to NB_PROCS, because there is
    293 // one ICU per processor.
    294 ////////////////////////////////////////////////////////////////////////////////
    295 
    296 ////////////////////////////////////////////////////////////////////////////////
    297 // _icu_write()
    298 //
     322    unsigned int        tty_id = _get_current_context_slot(CTX_TTY_ID);
     323    if ( tty_id >= NB_TTYS )
     324    {
     325        _tty_error();
     326        return 0;
     327    }
     328
     329    unsigned int*       tty_address = (unsigned int*)&seg_tty_base + tty_id*TTY_SPAN;
     330
     331    if ((tty_address[TTY_STATUS] & 0x1) != 0x1)
     332    {
     333        return 0;
     334    }
     335    else
     336    {
     337        *buffer = (char)tty_address[TTY_READ];
     338        return 1;
     339    }
     340}
     341
     342////////////////////////////////////////////////////////////////////////////////
     343//      VciMultiIcu and VciXicu drivers
     344////////////////////////////////////////////////////////////////////////////////
     345// There is in principle one vci_multi_icu (or vci_xicu) component per cluster,
     346// and the number of independant ICUs is equal to NB_PROCS_MAX, because there is
     347// one private interrupr controler per processor.
     348////////////////////////////////////////////////////////////////////////////////
     349
     350////////////////////////////////////////////////////////////////////////////////
     351//     _icu_write()
    299352// Write a 32-bit word in a memory mapped register of the MULTI_ICU device,
    300353// identified by the cluster index, and a processor local index.
     
    306359                         unsigned int value )
    307360{
    308     unsigned int *icu_address;
     361#if GIET_USE_XICU
     362
     363#else
    309364
    310365    // parameters checking
    311366    if ( register_index >= ICU_SPAN)            return 1;
    312367    if ( cluster_index >= NB_CLUSTERS)          return 1;
    313     if ( proc_index >= NB_PROCS )           return 1;
    314 
    315     icu_address = (unsigned int*)&seg_icu_base +
    316                   ( cluster_index * CLUSTER_SPAN )  +
    317                   ( proc_index * ICU_SPAN );
     368    if ( proc_index >= NB_PROCS_MAX )       return 1;
     369
     370    unsigned int *icu_address = (unsigned int*)&seg_icu_base +
     371                                (cluster_index * CLUSTER_SPAN)  +
     372                                (proc_index * ICU_SPAN);
    318373
    319374    icu_address[register_index] = value;   // write word
    320375    return 0;
    321 }
    322 
    323 ////////////////////////////////////////////////////////////////////////////////
    324 // _icu_read()
    325 //
     376
     377#endif
     378}
     379////////////////////////////////////////////////////////////////////////////////
     380//     _icu_read()
    326381// Read a 32-bit word in a memory mapped register of the MULTI_ICU device,
    327382// identified by the cluster index and a processor local index.
     
    333388                         unsigned int* buffer )
    334389{
    335     unsigned int *icu_address;
     390#if GIET_USE_XICU
     391
     392#else
    336393
    337394    // parameters checking
    338395    if ( register_index >= ICU_SPAN)            return 1;
    339396    if ( cluster_index >= NB_CLUSTERS)          return 1;
    340     if ( proc_index >= NB_PROCS )           return 1;
    341 
    342     icu_address = (unsigned int*)&seg_icu_base +
    343                   ( cluster_index * CLUSTER_SPAN )  +
    344                   ( proc_index * ICU_SPAN );
     397    if ( proc_index >= NB_PROCS_MAX )       return 1;
     398
     399    unsigned int *icu_address = (unsigned int*)&seg_icu_base +
     400                                (cluster_index * CLUSTER_SPAN)  +
     401                                (proc_index * ICU_SPAN);
    345402
    346403    *buffer = icu_address[register_index]; // read word
    347404    return 0;
     405
     406#endif
    348407}
    349408
     
    357416
    358417////////////////////////////////////////////////////////////////////////////////
    359 // _gcd_write()
    360 //
     418//     _gcd_write()
    361419// Write a 32-bit word in a memory mapped register of the GCD coprocessor.
    362420// Returns 0 if success, > 0 if error.
     
    376434    return 0;
    377435}
    378 
    379 ////////////////////////////////////////////////////////////////////////////////
    380 // _gcd_read()
    381 //
     436////////////////////////////////////////////////////////////////////////////////
     437//     _gcd_read()
    382438// Read a 32-bit word in a memory mapped register of the GCD coprocessor.
    383439// Returns 0 if success, > 0 if error.
     
    448504///////////////////////////////////////////////////////////////////////////////
    449505
     506// IOC global variables
     507in_unckdata volatile unsigned int       _ioc_status       = 0;
     508in_unckdata volatile unsigned int       _ioc_done         = 0;
     509in_unckdata unsigned int                        _ioc_lock         = 0;
     510in_unckdata unsigned int                        _ioc_iommu_ix1    = 0;
     511in_unckdata unsigned int                        _ioc_iommu_npages;
     512
    450513///////////////////////////////////////////////////////////////////////////////
    451 // _ioc_get_lock()
    452 //
    453 // This blocking helper is used by '_ioc_read()' and '_ioc_write()' functions
    454 // to get _ioc_lock using atomic LL/SC.
    455 ///////////////////////////////////////////////////////////////////////////////
    456 static inline void _ioc_get_lock()
    457 {
    458     register unsigned int delay = (_proctime() & 0xF) << 4;
    459     register unsigned int *plock = (unsigned int*)&_ioc_lock;
    460 
    461     asm volatile (
    462             "_ioc_llsc:             \n"
    463             "ll   $2,    0(%0)      \n" /* $2 <= _ioc_lock current value */
    464             "bnez $2,    _ioc_delay \n" /* delay if _ioc_lock already taken */
    465             "li   $3,    1          \n" /* $3 <= argument for sc */
    466             "sc   $3,    0(%0)      \n" /* try to set _ioc_lock */
    467             "bnez $3,    _ioc_ok    \n" /* exit if atomic */
    468             "_ioc_delay:            \n"
    469             "move $4,    %1         \n" /* $4 <= delay */
    470             "_ioc_loop:             \n"
    471             "beqz $4,    _ioc_loop  \n" /* test end delay */
    472             "addi $4,    $4,    -1  \n" /* $4 <= $4 - 1 */
    473             "j           _ioc_llsc  \n" /* retry ll */
    474             "nop                    \n"
    475             "_ioc_ok:               \n"
    476             :
    477             :"r"(plock), "r"(delay)
    478             :"$2", "$3", "$4");
    479 }
    480 
    481 ///////////////////////////////////////////////////////////////////////////////
    482 //  _ioc_access()
     514//      _ioc_access()
    483515// This function transfer data between a memory buffer and the block device.
    484516// The buffer lentgth is (count*block_size) bytes.
    485 //
    486517// Arguments are:
    487518// - to_mem     : from external storage to memory when non 0
     
    503534    unsigned int                ix2;                    // page index in IOMMU PT1 page table
    504535    unsigned int                addr;                   // buffer address for IOC peripheral
    505     unsigned int                user_ptp;               // page table pointer in user space
    506     unsigned int                ko;                             // bool returned by _v2p_translate()
    507536    unsigned int                ppn_first;              // first physical page number for user buffer
    508     unsigned int                ltid;                   // current task local index
    509     static_scheduler_t* psched;                 // pointer on the current task scheduler
    510537       
    511538    // check buffer alignment
     
    517544
    518545    // get user space page table virtual address
    519     psched   = &_scheduler[_procid()];
    520     ltid     = psched->current;
    521     user_ptp = psched->context[ltid][CTX_PTAB_ID];
     546    unsigned int user_pt_vbase = _get_current_context_slot(CTX_PTAB_ID);
    522547   
    523548    user_vpn_min = user_vaddr >> 12;
     
    529554    {
    530555        // get ppn and flags for each vpn
    531         ko = _v2p_translate( (page_table_t*)user_ptp,
    532                              vpn,
    533                              &ppn,
    534                              &flags );
     556        unsigned int ko = _v2p_translate( (page_table_t*)user_pt_vbase,
     557                                           vpn,
     558                                           &ppn,
     559                                           &flags );
    535560
    536561        // check access rights
     
    573598
    574599    // get the lock on ioc device
    575     _ioc_get_lock();
     600    _get_lock( &_ioc_lock );
    576601
    577602    // peripheral configuration 
     
    584609    return 0;
    585610}
    586 
    587611/////////////////////////////////////////////////////////////////////////////////
    588612// _ioc_completed()
     
    630654    return ret;
    631655}
    632 
    633656///////////////////////////////////////////////////////////////////////////////
    634 // _ioc_read()
     657//     _ioc_read()
    635658// Transfer data from the block device to a memory buffer in user space.
    636659// - lba    : first block index on the block device
     
    643666                        unsigned int    count )
    644667{
    645     return _ioc_access( 1,              // read
     668    return _ioc_access( 1,              // read access
    646669                        lba,
    647670                        (unsigned int)buffer,
    648671                        count );
    649672}
    650 
    651673///////////////////////////////////////////////////////////////////////////////
    652 // _ioc_write()
     674//     _ioc_write()
    653675// Transfer data from a memory buffer in user space to the block device.
    654676// - lba    : first block index on the block device
     
    661683                         unsigned int   count )
    662684{
    663     return _ioc_access( 0,              // write
     685    return _ioc_access( 0,              // write access
    664686                        lba,
    665687                        (unsigned int)buffer,
     
    668690
    669691//////////////////////////////////////////////////////////////////////////////////
     692// VciMultiDma driver
     693//////////////////////////////////////////////////////////////////////////////////
     694// The DMA controllers are physically distributed in the clusters.
     695// There is  (NB_CLUSTERS * NB_DMAS_MAX) channels, indexed by a global index:
     696//        dma_id = cluster_id * NB_DMA_MAX + loc_id
     697//
     698// As a DMA channel can be used by several tasks, each DMA channel is protected
     699// by a specific lock: _dma_lock[dma_id]
     700// The signalisation between the OS and the DMA uses the _dma_done[dma_id]
     701// synchronisation variables  (set by the ISR, and reset by the OS).
     702// The transfer status is copied by the ISR in the _dma_status[dma_id] variables.
     703//
     704// These DMA channels can be used by the FB driver, or by the NIC driver.
     705//////////////////////////////////////////////////////////////////////////////////
     706
     707#if  (NB_DMAS_MAX > 0)
     708in_unckdata unsigned int                        _dma_lock[NB_DMAS_MAX * NB_CLUSTERS]
     709                                       = { [0 ... (NB_DMAS_MAX * NB_CLUSTERS)-1] = 0 };
     710
     711in_unckdata volatile unsigned int       _dma_done[NB_DMAS_MAX * NB_CLUSTERS]
     712                                       = { [0 ... (NB_DMAS_MAX * NB_CLUSTERS)-1] = 0 };
     713
     714in_unckdata volatile unsigned int       _dma_status[NB_DMAS_MAX * NB_CLUSTERS];
     715
     716in_unckdata unsigned int                        _dma_iommu_ix1 = 1;
     717
     718in_unckdata unsigned int            _dma_iommu_npages[NB_DMAS_MAX * NB_CLUSTERS];
     719#endif
     720
     721//////////////////////////////////////////////////////////////////////////////////
    670722//      VciFrameBuffer driver
    671723//////////////////////////////////////////////////////////////////////////////////
     724// The vci_frame_buffer device can be accessed directly by software with memcpy(),
     725// or it can be accessed through a multi-channels DMA component:
     726// 
    672727// The '_fb_sync_write' and '_fb_sync_read' functions use a memcpy strategy to
    673728// implement the transfer between a data buffer (user space) and the frame
     
    675730//
    676731// The '_fb_write()', '_fb_read()' and '_fb_completed()' functions use the DMA
    677 // coprocessor to transfer data between the user buffer and the frame buffer.
    678 // These  functions use a polling policy to test the global variables _dma_busy[i]
    679 // and detect the transfer completion. 
    680 // There is  NB_DMA channels, that are indexed by the dma_id stored in the
    681 // task context.
    682 // The _dma_busy[i] synchronisation variables (one per channel) are set by the OS,
    683 // and reset by the DMA ISR.
     732// controlers (distributed in the clusters) to transfer data
     733// between the user buffer and the frame buffer. A  DMA channel is
     734// allocated to each task requesting it in the mapping_info data structure.
    684735//////////////////////////////////////////////////////////////////////////////////
    685736
     
    697748                             unsigned int       length )
    698749{
    699     volatile unsigned char *fb_address;
    700750
    701751    // buffer must be mapped in user space
    702752    if ( ((unsigned int)buffer + length ) >= 0x80000000 )
     753    {
    703754        return 1;
    704 
    705     fb_address = (unsigned char*)&seg_fb_base + offset;
    706 
    707     // buffer copy
    708     memcpy((void*)fb_address, (void*)buffer, length);
    709 
    710     return 0;
     755    }
     756    else
     757    {
     758        unsigned char *fb_address = (unsigned char*)&seg_fb_base + offset;
     759        memcpy((void*)fb_address, (void*)buffer, length);
     760        return 0;
     761    }
    711762}
    712763
     
    724775                            unsigned int        length )
    725776{
    726     volatile unsigned char *fb_address;
    727 
    728777    // buffer must be mapped in user space
    729778    if ( ((unsigned int)buffer + length ) >= 0x80000000 )
     779    {
    730780        return 1;
    731 
    732     fb_address = (unsigned char*)&seg_fb_base + offset;
    733 
    734     // buffer copy
    735     memcpy((void*)buffer, (void*)fb_address, length);
    736 
    737     return 0;
    738 }
    739 
    740 //////////////////////////////////////////////////////////////////////////////////
    741 // _fb_access()
    742 // Transfer data between a memory buffer and the frame_buffer device using DMA.
    743 // - to_mem     : from frame buffer to memory when true.
     781    }
     782    else
     783    {
     784        unsigned char *fb_address = (unsigned char*)&seg_fb_base + offset;
     785        memcpy((void*)buffer, (void*)fb_address, length);
     786        return 0;
     787    }
     788}
     789
     790//////////////////////////////////////////////////////////////////////////////////
     791// _fb_dma_access()
     792// Transfer data between a user buffer and the frame_buffer using DMA.
     793// - to_user    : from frame buffer to user buffer when true.
    744794// - offset     : offset (in bytes) in the frame buffer.
    745795// - user_vaddr : virtual base address of the memory buffer.
     
    747797// The memory buffer must be mapped in user address space and word-aligned.
    748798// The user buffer length must be multiple of 4 bytes.
    749 // Returns 0 if success, > 0 if error.
    750 //////////////////////////////////////////////////////////////////////////////////
    751 unsigned int _fb_access( unsigned int   to_mem,
    752                          unsigned int   offset,
    753                          unsigned int   user_vaddr,
    754                          unsigned int   length )
    755 {
    756     static_scheduler_t* psched;         // pointer on the current task scheduler
    757     unsigned char*              fb_base;        // frame buffer base address
    758     unsigned int*               dma_base;       // dma component base address
    759     unsigned int                task_id;        // task local index (for scheduler)
    760     unsigned int                dma_id;         // DMA channel index
    761     unsigned int                vpn;            // current virtual page number
    762     unsigned int                flags;          // protection flags
    763     unsigned int                ppn;            // current physical page number
    764     unsigned int                buf_base;       // buffer base address for DMA access
    765     unsigned int                ppn_first;      // first physical page index for user buffer
    766 
    767     fb_base  = (unsigned char*)&seg_fb_base + offset;
    768 
    769     psched   = &_scheduler[_procid()];
    770     task_id  = psched->current;
    771     dma_id   = psched->context[task_id][CTX_FBDMA_ID];
    772     dma_base = (unsigned int*)&seg_dma_base + (dma_id * DMA_SPAN);
    773 
    774     // check buffer address and ength alignment
    775     if ( user_vaddr & 0x3 ) return 1;
    776     if ( length     & 0x3 ) return 1;
     799// Me must compute the physical base addresses for both the frame buffer
     800// and the user buffer before programming the DMA transfer.
     801// The GIET being fully static, we don't need to split the transfer in 4Kbytes
     802// pages, because the user buffer is contiguous in physical space.
     803// Returns 0 if success, > 0 if error.
     804//////////////////////////////////////////////////////////////////////////////////
     805unsigned int _fb_dma_access( unsigned int       to_user,
     806                             unsigned int   offset,
     807                             unsigned int   user_vaddr,
     808                             unsigned int   length )
     809{
     810    unsigned int        ko;                             // unsuccessfull V2P translation
     811    unsigned int        flags;                  // protection flags
     812    unsigned int        ppn;                    // physical page number
     813    unsigned int    user_pbase;         // user buffer pbase address
     814    unsigned int    fb_pbase;           // frame buffer pbase address
     815
     816    // get DMA channel and compute DMA vbase address
     817    unsigned int        dma_id     = _get_current_context_slot(CTX_FBDMA_ID);
     818    unsigned int    cluster_id = dma_id / NB_DMAS_MAX;
     819    unsigned int    loc_id     = dma_id % NB_DMAS_MAX;
     820    unsigned int*       dma_base   = (unsigned int*)&seg_dma_base +
     821                                 (cluster_id * CLUSTER_SPAN) +
     822                                 (loc_id * DMA_SPAN);
     823
     824    // check user buffer address and length alignment
     825    if ( (user_vaddr & 0x3) || (length & 0x3) )
     826    {
     827        _puts("[GIET ERROR] in _fbdma_access() : user buffer not word aligned\n");
     828        return 1;
     829    }
    777830
    778831    // get user space page table virtual address
    779     unsigned int user_ptp = psched->context[task_id][CTX_PTAB_ID];
    780 
     832    unsigned int        user_ptab = _get_current_context_slot(CTX_PTAB_ID);
     833
     834    // compute frame buffer pbase address
     835    unsigned int fb_vaddr = (unsigned int)&seg_fb_base + offset;
     836
     837    ko = _v2p_translate( (page_table_t*)user_ptab,
     838                         (fb_vaddr >> 12),
     839                         &ppn,
     840                         &flags );
     841    fb_pbase = (ppn << 12) | (fb_vaddr & 0x00000FFF);
     842
     843    if ( ko )
     844    {
     845        _puts("[GIET ERROR] in _fbdma_access() : frame buffer unmapped\n");
     846        return 2;
     847    }
     848
     849    // Compute user buffer pbase address
     850    ko = _v2p_translate( (page_table_t*)user_ptab,
     851                         (user_vaddr >> 12),
     852                         &ppn,
     853                         &flags );
     854    user_pbase = (ppn << 12) | (user_vaddr & 0x00000FFF);
     855
     856    if ( ko )
     857    {
     858        _puts("[GIET ERROR] in _fbdma_access() : user buffer unmapped\n");
     859        return 3;
     860    }
     861    if ( (flags & PTE_U) == 0 )
     862    {
     863        _puts("[GIET ERROR] in _fbdma_access() : user buffer not in user space\n");
     864        return 4;
     865    }
     866    if ( ( (flags & PTE_W) == 0 ) && to_user )
     867    {
     868        _puts("[GIET ERROR] in _fbdma_access() : user buffer not writable\n");
     869        return 5;
     870    }
     871
     872
     873
     874/*
     875    // loop on all virtual pages covering the user buffer
    781876    unsigned int user_vpn_min = user_vaddr >> 12;
    782877    unsigned int user_vpn_max = (user_vaddr + length - 1) >> 12;
    783878    unsigned int ix2          = 0;
    784879    unsigned int ix1          = _dma_iommu_ix1 + dma_id;
    785     unsigned int ko;
    786     unsigned int i;
    787 
    788     // loop on all virtual pages covering the user buffer
     880
    789881    for ( vpn = user_vpn_min ; vpn <= user_vpn_max ; vpn++ )
    790882    {
    791883        // get ppn and flags for each vpn
    792         ko = _v2p_translate( (page_table_t*)user_ptp,
    793                              vpn,
    794                              &ppn,
    795                              &flags );
     884        unsigned int ko = _v2p_translate( (page_table_t*)user_pt_vbase,
     885                                          vpn,
     886                                          &ppn,
     887                                          &flags );
    796888
    797889        // check access rights
    798         if ( ko )                                 return 2;     // unmapped
    799         if ( (flags & PTE_U) == 0 )               return 3;     // not in user space
    800         if ( ( (flags & PTE_W) == 0 ) && to_mem ) return 4;     // not writable
     890        if ( ko )                                 return 3;     // unmapped
     891        if ( (flags & PTE_U) == 0 )               return 4;     // not in user space
     892        if ( ( (flags & PTE_W) == 0 ) && to_user ) return 5;     // not writable
    801893
    802894        // save first ppn value
     
    816908        else            // no IOMMU : check that physical pages are contiguous
    817909        {
    818             if ( (ppn - ppn_first) != ix2 )       return 5;     // split physical buffer 
     910            if ( (ppn - ppn_first) != ix2 )       return 6;     // split physical buffer 
    819911        }
    820912
     
    823915    } // end for vpn
    824916
    825     // register the number of pages to be unmapped
     917    // register the number of pages to be unmapped if iommu activated
    826918    _dma_iommu_npages[dma_id] = (user_vpn_max - user_vpn_min) + 1;
    827919
     920*/
    828921    // invalidate data cache in case of memory write
    829     if ( to_mem ) _dcache_buf_invalidate( (void*)user_vaddr, length );
    830 
    831     // compute buffer base address for DMA depending on IOMMU activation
    832     if ( GIET_IOMMU_ACTIVE ) buf_base = ( ix1 ) << 21 | (user_vaddr & 0xFFF);
    833     else                     buf_base = (ppn_first << 12) | (user_vaddr & 0xFFF);
    834 
    835 
    836     // waiting until DMA device is available
    837     while (_dma_busy[dma_id] != 0)
    838     {
    839         // busy wait with a pseudo random delay between bus access
    840         unsigned int delay = (_proctime() & 0xF) << 4;
    841         for (i = 0; i < delay; i++)
    842             asm volatile("nop");
    843     }
    844 
    845     _dma_busy[dma_id] = 1;
     922    if ( to_user ) _dcache_buf_invalidate( (void*)user_vaddr, length );
     923
     924    // get the lock
     925    _get_lock( &_dma_lock[dma_id] );
    846926
    847927    // DMA configuration
    848     dma_base[DMA_IRQ_DISABLE] = 0;
    849     if ( to_mem )
    850     {
    851         dma_base[DMA_SRC] = (unsigned int)fb_base;
    852         dma_base[DMA_DST] = (unsigned int)buf_base;
     928    if ( to_user )
     929    {
     930        dma_base[DMA_SRC] = (unsigned int)fb_pbase;
     931        dma_base[DMA_DST] = (unsigned int)user_pbase;
    853932    }
    854933    else
    855934    {
    856         dma_base[DMA_SRC] = (unsigned int)buf_base;
    857         dma_base[DMA_DST] = (unsigned int)fb_base;
     935        dma_base[DMA_SRC] = (unsigned int)user_pbase;
     936        dma_base[DMA_DST] = (unsigned int)fb_pbase;
    858937    }
    859938    dma_base[DMA_LEN] = (unsigned int)length;
     
    873952                        unsigned int    length )
    874953{
    875     return _fb_access( 0,                                               // write to frame buffer
    876                        offset,
    877                        (unsigned int)buffer,
    878                        length );       
     954    return _fb_dma_access( 0,                                           // write to frame buffer
     955                           offset,
     956                           (unsigned int)buffer,
     957                           length );   
    879958}
    880959
     
    891970                       unsigned int     length )
    892971{
    893     return _fb_access( 1,                                               // read from frame buffer
    894                        offset,
    895                        (unsigned int)buffer,
    896                        length );       
     972    return _fb_dma_access( 1,                                           // read from frame buffer
     973                           offset,
     974                           (unsigned int)buffer,
     975                           length );   
    897976}
    898977
     
    906985unsigned int _fb_completed()
    907986{
    908     static_scheduler_t* psched  = &_scheduler[_procid()];
    909     unsigned int        task_id = psched->current;
    910 
    911     volatile unsigned int   dma_id  = psched->context[task_id][CTX_FBDMA_ID];
     987    unsigned int dma_id = _get_current_context_slot(CTX_FBDMA_ID);
    912988
    913989    // busy waiting with a pseudo random delay between bus access
    914     while (_dma_busy[dma_id] != 0)
     990    while (_dma_done[dma_id] == 0)
    915991    {
    916992            unsigned int i;
    917         unsigned int delay = (_proctime() & 0xF) << 4;
     993        unsigned int delay = ( _proctime() ^ _procid()<<4 ) & 0xFF;
    918994        for (i = 0; i < delay; i++)
    919995            asm volatile("nop");
     
    9381014    }
    9391015
     1016    // reset synchronization variables
     1017    _dma_lock[dma_id] = 0;
     1018    _dma_done[dma_id] = 0;
     1019
    9401020    return _dma_status[dma_id];
    9411021}
  • soft/giet_vm/sys/drivers.h

    r166 r189  
    1010
    1111///////////////////////////////////////////////////////////////////////////////////
    12 //      Global variables for interaction with ISRs
     12// Timer access functions (used for both vci_multi_timer and vci_xicu)
    1313///////////////////////////////////////////////////////////////////////////////////
    1414
    15 extern volatile unsigned int _dma_status[];
    16 extern volatile unsigned char _dma_busy[];
     15extern volatile unsigned char _timer_event[];
    1716
    18 extern volatile unsigned char _ioc_status;
    19 extern volatile unsigned char _ioc_done;
    20 extern unsigned int           _ioc_lock;
     17unsigned int _timer_access( unsigned int        read,           // reas if non 0
     18                            unsigned int        cluster_id,
     19                            unsigned int        local_id,
     20                            unsigned int        register_id,
     21                            unsigned int*       buffer);
     22
     23unsigned int _timer_read(   unsigned int        register_id,
     24                            unsigned int*       buffer);
     25
     26unsigned int _timer_write(  unsigned int        register_id,
     27                            unsigned int        value);
     28
     29///////////////////////////////////////////////////////////////////////////////////
     30// TTY access functions and variables
     31///////////////////////////////////////////////////////////////////////////////////
    2132
    2233extern volatile unsigned char _tty_get_buf[];
    2334extern volatile unsigned char _tty_get_full[];
    2435extern unsigned int           _tty_put_lock;
    25 
    26 ///////////////////////////////////////////////////////////////////////////////////
    27 // Prototypes of the external functions.
    28 ///////////////////////////////////////////////////////////////////////////////////
    29 
    30 unsigned int _timer_write(  unsigned int        cluster_id,
    31                             unsigned int        timer_id,
    32                             unsigned int        register_id,
    33                             unsigned int        value);
    34 
    35 unsigned int _timer_read(   unsigned int        cluster_id,
    36                             unsigned int        timer_id,
    37                             unsigned int        register_id,
    38                             unsigned int*       buffer);
    39 
    40 unsigned int _icu_write(    unsigned int        cluster_id,
    41                             unsigned int        proc_id,
    42                             unsigned int        register_id,
    43                             unsigned int        value);
    44 
    45 unsigned int _icu_read(     unsigned int        cluster_id,
    46                             unsigned int        proc_id,
    47                             unsigned int        register_id,
    48                             unsigned int*       buffer);
    4936
    5037unsigned int _tty_write(    const char*         buffer,
     
    5643unsigned int _tty_read_irq( char*                       buffer,
    5744                            unsigned int        length);
     45
     46///////////////////////////////////////////////////////////////////////////////////
     47// ICU access functions (both vci_multi_icu and vci_xicu)
     48///////////////////////////////////////////////////////////////////////////////////
     49
     50unsigned int _icu_read(     unsigned int        cluster_id,
     51                            unsigned int        proc_id,
     52                            unsigned int        register_id,
     53                            unsigned int*       buffer);
     54
     55unsigned int _icu_write(        unsigned int    cluster_id,
     56                                                        unsigned int    proc_id,
     57                                                        unsigned int    register_id,
     58                                                        unsigned int    value );
     59
     60///////////////////////////////////////////////////////////////////////////////////
     61// IOC access functions and variables (vci_block_device)
     62///////////////////////////////////////////////////////////////////////////////////
     63
     64extern volatile unsigned int    _ioc_status;
     65extern volatile unsigned int    _ioc_done;
     66extern unsigned int                             _ioc_lock;
     67extern unsigned int                             _ioc_iommu_ix1;
     68extern unsigned int                             _ioc_iommu_npages;
     69
    5870
    5971unsigned int _ioc_write(    unsigned int        lba,
     
    6779unsigned int _ioc_completed();
    6880
    69 unsigned int _gcd_write(    unsigned int        register_index,
    70                             unsigned int        value);
     81///////////////////////////////////////////////////////////////////////////////////
     82// Multi DMA variables                  (vci_multi_dma)
     83///////////////////////////////////////////////////////////////////////////////////
     84 
     85extern volatile unsigned int    _dma_status[];
     86extern volatile unsigned int    _dma_done[];
     87extern unsigned int                             _dma_lock[];
     88extern unsigned int                             _dma_iommu_ix1;
     89extern unsigned int                             _dma_iommu_npages[];
    7190
    72 unsigned int _gcd_read(     unsigned int        register_index,
    73                             unsigned int*       buffer);
    74 
     91///////////////////////////////////////////////////////////////////////////////////
     92// Frame Buffer access functions  (vci_frame_buffer)
     93///////////////////////////////////////////////////////////////////////////////////
     94 
    7595unsigned int _fb_sync_write(unsigned int        offset,
    7696                            const void*         buffer,
     
    91111unsigned int _fb_completed();
    92112
     113///////////////////////////////////////////////////////////////////////////////////
     114// GCD access functions
     115///////////////////////////////////////////////////////////////////////////////////
     116
     117unsigned int _gcd_write(    unsigned int        register_index,
     118                            unsigned int        value);
     119
     120unsigned int _gcd_read(     unsigned int        register_index,
     121                            unsigned int*       buffer);
     122
     123
    93124#endif
    94125
  • soft/giet_vm/sys/exc_handler.c

    r158 r189  
    3232
    3333///////////////////////////////////////////////////////////////////////////////////
    34 // Initialize the exception vector according to CR code
     34// Initialize the exception vector indexed by the CR XCODE field
    3535///////////////////////////////////////////////////////////////////////////////////
    3636const _exc_func_t _cause_vector[16] = {
     
    6767static void _cause(unsigned int msg_cause)
    6868{
    69     unsigned int        epc;
    70     unsigned int        bar;
    71     unsigned int        cause;
    72 
    73     asm volatile("mfc0 %0, $14" : "=r"(epc));
    74     asm volatile("mfc0 %0, $8 " : "=r"(bar));
    75     asm volatile("mfc0 %0, $13" : "=r"(cause));
    76 
    7769    _puts( (char*)(exc_message_causes[msg_cause]) );
    78     _puts("\nEPC   = ");
    79     _putw( epc );
    80     _puts("\nBAR   = ");
    81     _putw( bar );
    82     _puts("\nCAUSE = ");
    83     _putw( cause );
     70    _puts("\n - Cycle     : ");
     71    _putd( _proctime() );
     72    _puts("\n - Processor : ");
     73    _putd( _procid() );
     74    _puts("\n - Task      : ");
     75    _putd( _get_current_task_id() );
     76    _puts("\n - EPC       : ");
     77    _putw( _get_epc() );
     78    _puts("\n - BVAR      : ");
     79    _putw( _get_bvar() );
    8480    _puts("\n");
    85 
    8681    _exit();
    8782}
  • soft/giet_vm/sys/giet.s

    r165 r189  
    126126    sw      $27,    22*4($29)       /* save EPC */
    127127
    128     la      $26,    _int_demux
     128    la      $26,    _irq_demux
    129129    jalr    $26                     /* jump to a C function to find the proper ISR */
    130130
  • soft/giet_vm/sys/irq_handler.c

    r169 r189  
    22// File     : irq_handler.c
    33// Date     : 01/04/2012
    4 // Author   : alain greiner and joel porquet
     4// Author   : alain greiner
    55// Copyright (c) UPMC-LIP6
    66///////////////////////////////////////////////////////////////////////////////////
    7 // The irq_handler.c and irq_handler.h files are part of the GIET nano-kernel.
    8 // They contain the code of the _int_demux function that handle
    9 // the ICU (Interupt Controler Unit), and the various ISRs associated
    10 // to the CoCLib peripherals.
     7// The irq_handler.c and irq_handler.h files are part of the GIET-VM nano-kernel.
     8// They contain the code of the _irq_demux() function that access the XICU or
     9// ICU component (Interupt Controler Unit), and the various ISRs (Interrupt
     10// Service Routine) associated to the peripherals.
    1111///////////////////////////////////////////////////////////////////////////////////
    1212
     
    2020
    2121///////////////////////////////////////////////////////////////////////////////////
    22 // Initialize the whole interrupt vector with the default ISR
    23 ///////////////////////////////////////////////////////////////////////////////////
    24 
    25 __attribute__((section (".kdata"))) _isr_func_t _interrupt_vector[32] =
    26                                                   { [0 ... 31] = &_isr_default };
    27 
    28 ///////////////////////////////////////////////////////////////////////////////////
    29 //      _int_demux()
    30 // This functions uses an external ICU component (Interrupt Controler Unit)
    31 // that concentrates up to 32 input interrupts lines. This component
    32 // can support up to NB_PROCS output IRQ.
     22//      _irq_demux()
     23// This function uses the ICU or XICU component (Interrupt Controler Unit)
     24// to get the interrupt vector entry. There is one ICU or XICU component per
     25// cluster, and this component can support up to NB_PROCS_MAX output IRQs.
     26// It returns the highest priority active interrupt index (smaller
     27// indexes have the highest priority).
     28// Any value larger than 31 means "no active interrupt", and no ISR is executed.
    3329//
    34 // This component returns the highest priority active interrupt index (smaller
    35 // indexes have the highest priority) by reading the ICU_IT_VECTOR register.
    36 // Any value larger than 31 means "no active interrupt", and the default ISR
    37 // (that does nothing) is executed.
     30// There is one interrupt vector per processor (stored in the scheduler associated
     31// to the processor. Each interrupt vector entry contains two 16 bits fields:
     32// - isr_id : defines the type of ISR to be executed.
     33// - channel_id : defines the specific channel for multi-channels peripherals.
    3834//
    39 // The interrupt vector (32 ISR addresses array stored at _interrupt_vector
    40 // address) is initialised with the default ISR address. The actual ISR
    41 // addresses are supposed to be written in the interrupt vector array
    42 // during system initialisation.
    43 ///////////////////////////////////////////////////////////////////////////////////
    44 void _int_demux(void)
    45 {
    46     int                         interrupt_index;
    47     _isr_func_t         isr;
    48     unsigned int        pid = _procid();
    49 
    50     // retrieves the highest priority active interrupt index
    51     if (!_icu_read( pid / NB_PROCS,
    52                     pid % NB_PROCS,
     35// If the peripheral is replicated in clusters (TIMER or DMA), the channel_id is
     36// a global index : channel_id = cluster_id * NB_CHANNELS_MAX + loc_id   
     37///////////////////////////////////////////////////////////////////////////////////
     38void _irq_demux()
     39{
     40    unsigned int    pid = _procid();
     41    unsigned int        irq_id;
     42
     43    // get the highest priority active IRQ index
     44
     45#if GIET_USE_XICU
     46
     47#else
     48
     49    if ( _icu_read( pid / NB_PROCS_MAX,
     50                    pid % NB_PROCS_MAX,
    5351                    ICU_IT_VECTOR,
    54                     (unsigned int*)&interrupt_index ) )
     52                    &irq_id ) )
    5553    {
    56         if (interrupt_index == -1)      // no interrupt is active
    57             return;
    58 
    59         isr = _interrupt_vector[interrupt_index];
    60         isr();
    61     }
    62     else
    63     {
    64         _puts("\n[GIET ERROR] In _demux function : wrong arguments in _icu_read()\n");
     54        _puts("\n[GIET ERROR] wrong _icu_read in _irq_demux() function\n");
    6555        _exit();
    6656    }
     57
     58#endif
     59
     60    if ( irq_id < 32 )  // do nothing if no interrupt active
     61    {
     62        unsigned int entry      = _get_interrupt_vector_entry(irq_id);
     63        unsigned int isr_id     = entry & 0x000000FF;
     64        unsigned int channel_id = (entry>>16) & 0x0000FFFF;
     65        if      ( isr_id == ISR_SWITCH  ) _isr_switch();
     66        else if ( isr_id == ISR_IOC     ) _isr_ioc();
     67        else if ( isr_id == ISR_DMA     ) _isr_dma( channel_id );
     68        else if ( isr_id == ISR_TTY     ) _isr_tty( channel_id );
     69        else if ( isr_id == ISR_TIMER   ) _isr_timer( channel_id );
     70        else                              _isr_default();
     71    }
    6772}
    6873///////////////////////////////////////////////////////////////////////////////////
    6974//      _isr_default()
    7075// The default ISR is called when no specific ISR has been installed in the
    71 // interrupt vector. It simply displays a message on TTY0.
     76// interrupt vector. It simply displays a message on kernel TTY[0].
    7277///////////////////////////////////////////////////////////////////////////////////
    7378void _isr_default()
    7479{
    75     _puts("\n\n!!! Default ISR !!!\n");
     80    _puts("\n\n!!! Strange... Default ISR activated !!!\n");
    7681}
    7782
    7883///////////////////////////////////////////////////////////////////////////////////
    7984//      _isr_dma()
    80 // This ISR handles up to 8 IRQs generated by 8 independant channels of the
    81 // multi_dma component. It acknowledges the interrupt and reset the synchronisation
    82 // variable _dma_busy[i], after copying the status into the _dma_status[i] variable.
    83 ///////////////////////////////////////////////////////////////////////////////////
    84 void _isr_dma_indexed( unsigned int dma_id )
    85 {
    86     volatile unsigned int* dma_address;
     85// This ISR handles all IRQs generated by the multi-channels DMA controlers.
     86// The multi_dma components can be distributed in the clusters.
     87// The channel_id argument is the global DMA channel index.
     88//     channel_id = cluster_id*NB_DMAS_MAX + loc_id
     89// - The ISR saves the transfert status in _dma_status[channel_id].
     90// - It acknowledges the interrupt to reinitialize the DMA controler.
     91// - it resets the synchronisation variable _dma_busy[channel_id].
     92///////////////////////////////////////////////////////////////////////////////////
     93void _isr_dma( unsigned int channel_id )
     94{
     95    // compute cluster_id and loc_id
     96    unsigned int cluster_id = channel_id / NB_DMAS_MAX;
     97    unsigned int loc_id     = channel_id % NB_DMAS_MAX;
    8798
    8899    // compute DMA channel address
    89     dma_address = (unsigned int*)&seg_dma_base + (dma_id * DMA_SPAN);
     100    unsigned int*       dma_address = (unsigned int*)&seg_dma_base +
     101                                  (loc_id * DMA_SPAN) +
     102                                  (cluster_id * CLUSTER_SPAN);
    90103
    91104    // save DMA channel status 
    92     _dma_status[dma_id] = dma_address[DMA_LEN]; /* save status */
     105    _dma_status[channel_id] = dma_address[DMA_LEN];
    93106
    94107    // reset DMA channel
    95     dma_address[DMA_RESET] = 0;                                 /* reset IRQ */
     108    dma_address[DMA_RESET] = 0;                 
    96109
    97110    // release DMA channel
    98     _dma_busy[dma_id] = 0;                      /* release DMA */
    99 }
    100 
    101 void _isr_dma_0() { _isr_dma_indexed(0); }
    102 void _isr_dma_1() { _isr_dma_indexed(1); }
    103 void _isr_dma_2() { _isr_dma_indexed(2); }
    104 void _isr_dma_3() { _isr_dma_indexed(3); }
    105 void _isr_dma_4() { _isr_dma_indexed(4); }
    106 void _isr_dma_5() { _isr_dma_indexed(5); }
    107 void _isr_dma_6() { _isr_dma_indexed(6); }
    108 void _isr_dma_7() { _isr_dma_indexed(7); }
     111    _dma_done[channel_id] = 1; 
     112}
    109113
    110114///////////////////////////////////////////////////////////////////////////////////
    111115//      _isr_ioc()
    112 // There is only one IOC controler shared by all tasks. It acknowledge the IRQ
    113 // using the ioc base address, save the status, and set the _ioc_done variable
    114 // to signal completion.
     116// There is only one IOC controler shared by all tasks.
     117// - The ISR save the status and acknowledge the IRQ.
     118// - It sets the _ioc_done variable to signal completion.
    115119///////////////////////////////////////////////////////////////////////////////////
    116120void _isr_ioc()
    117121{
    118     volatile unsigned int* ioc_address;
    119 
    120     ioc_address = (unsigned int*)&seg_ioc_base;
     122    unsigned int* ioc_address = (unsigned int*)&seg_ioc_base;
    121123
    122124    _ioc_status = ioc_address[BLOCK_DEVICE_STATUS]; /* save status & reset IRQ */
     
    125127
    126128///////////////////////////////////////////////////////////////////////////////////
    127 //      _isr_timer_* (* = 0,1,2,3,4,5,6,7)
    128 // This ISR handles up to 8 IRQs generated by 8 independant timers.
    129 // It acknowledges the IRQ on TIMER[*] and displays a message on TTY0
    130 ///////////////////////////////////////////////////////////////////////////////////
    131 void _isr_timer_indexed(unsigned int timer_id)
    132 {
    133     volatile unsigned int *timer_address;
    134 
    135     timer_address = (unsigned int*)&seg_timer_base + (timer_id * TIMER_SPAN);
    136 
    137     timer_address[TIMER_RESETIRQ] = 0; /* reset IRQ */
    138 
    139     _puts("\n\n!!! Interrupt timer received from timer ");
    140     _putw( timer_id );
    141     _puts(" at cycle ");
    142     _putw( _proctime() );
    143     _puts("\n\n");
    144 }
    145 
    146 void _isr_timer_0()  { _isr_timer_indexed(0);  }
    147 void _isr_timer_1()  { _isr_timer_indexed(1);  }
    148 void _isr_timer_2()  { _isr_timer_indexed(2);  }
    149 void _isr_timer_3()  { _isr_timer_indexed(3);  }
    150 void _isr_timer_4()  { _isr_timer_indexed(4);  }
    151 void _isr_timer_5()  { _isr_timer_indexed(5);  }
    152 void _isr_timer_6()  { _isr_timer_indexed(6);  }
    153 void _isr_timer_7()  { _isr_timer_indexed(7);  }
    154 
    155 ///////////////////////////////////////////////////////////////////////////////////
    156 // _isr_tty_get_* (* = 0,1,2,3,4,5,6,7,9,10,11,12,13,14,15)
    157 // The Giet supports up to 16 TTY terminals.
    158 // These 16 ISRs handle the up to 16 IRQs associated to 16 independant
    159 // terminals, signaling that a character is available.
    160 // There is one communication buffer _tty_get_buf[tty_id] per terminal.
    161 // The sychronisation variable _tty_get_full[tty_id], is set by the ISR,
     129//         _isr_timer()
     130// This ISR handles the IRQs generated by the "user" timers (the IRQs
     131// generated by the "system" timers should be handled by the _isr_switch().
     132// These timers are distributed in all clusters, and can be implemented
     133// in a vci_multi_timer component, or in a vci_xicu component.
     134// The channel_id argument is the global channel index:
     135//     channel_id = cluster_id*(NB_TIMERS_MAX+NB_PROCS_MAX) + loc_id
     136// The user timer local index is (loc_id - NB_PROCS_MAX).
     137//
     138// The ISR acknowledges the IRQ and registers the event in the proper entry
     139// of the _timer_event[] array.
     140// A log message is displayed on the kernel terminal.
     141///////////////////////////////////////////////////////////////////////////////////
     142void _isr_timer(unsigned int channel_id)
     143{
     144
     145    unsigned int cluster_id = channel_id / (NB_TIMERS_MAX + NB_PROCS_MAX);
     146    unsigned int loc_id     = channel_id % (NB_TIMERS_MAX + NB_PROCS_MAX);
     147
     148    if (loc_id < NB_PROCS_MAX )
     149    {
     150        _puts("[GIET ERROR] Receiving a user timer IRQ for a system timer\n");
     151        _puts("             cluster = ");
     152        _putw(cluster_id);
     153        _puts(" / local_id = ");
     154        _putw(loc_id);
     155    }
     156
     157#if GIET_USE_XICU
     158
     159// TODO
     160
     161#else
     162
     163    // compute Timer address
     164    unsigned int* timer_address = (unsigned int*)&seg_timer_base +
     165                                  (loc_id * TIMER_SPAN) +
     166                                  (cluster_id * CLUSTER_SPAN);
     167
     168    // reset IRQ
     169    timer_address[TIMER_RESETIRQ] = 0;
     170
     171#endif
     172
     173#if NB_TIMERS_MAX
     174    // register the event
     175    _timer_event[(cluster_id*NB_TIMERS_MAX) + (loc_id - NB_PROCS_MAX)] = 1;
     176#endif
     177
     178    // display a message on TTY 0
     179    _puts("[GIET] User Timer IRQ / cluster = ");
     180    _putw(cluster_id);
     181    _puts(" / timer = ");
     182    _putw(loc_id - NB_PROCS_MAX);
     183    _puts("\n");
     184}
     185
     186///////////////////////////////////////////////////////////////////////////////////
     187//  _isr_tty()
     188// This ISR handles the IRQs generated by the multi_tty controler,
     189// signaling that a character is available.
     190// There is one single multi_tty component controling all TTYs, and the tty_id
     191// argument is the global TTY index.
     192// There is one communication buffer _tty_buf[tty_id] per terminal.
     193// The sychronisation variable _tty_full[tty_id], is set by the ISR,
    162194// and reset by the OS.
    163195// A character is lost if the buffer is full when the ISR is executed.
    164196///////////////////////////////////////////////////////////////////////////////////
    165 void _isr_tty_get_indexed(unsigned int tty_id)
    166 {
    167     volatile unsigned int *tty_address;
    168 
    169     /* compute terminal base address */
    170     tty_address = (unsigned int*)&seg_tty_base + (tty_id * TTY_SPAN);
    171 
    172     /* save character and reset IRQ */
     197void _isr_tty(unsigned int tty_id)
     198{
     199    // compute terminal base address
     200    unsigned int *tty_address = (unsigned int*)&seg_tty_base + (tty_id * TTY_SPAN);
     201
     202    // save character and reset IRQ
    173203    _tty_get_buf[tty_id] = (unsigned char)tty_address[TTY_READ];
    174204
    175     /* signals character available */
     205    // signals character available
    176206    _tty_get_full[tty_id] = 1;
    177207}
    178 
    179 void _isr_tty_get_0()  { _isr_tty_get_indexed(0);  }
    180 void _isr_tty_get_1()  { _isr_tty_get_indexed(1);  }
    181 void _isr_tty_get_2()  { _isr_tty_get_indexed(2);  }
    182 void _isr_tty_get_3()  { _isr_tty_get_indexed(3);  }
    183 void _isr_tty_get_4()  { _isr_tty_get_indexed(4);  }
    184 void _isr_tty_get_5()  { _isr_tty_get_indexed(5);  }
    185 void _isr_tty_get_6()  { _isr_tty_get_indexed(6);  }
    186 void _isr_tty_get_7()  { _isr_tty_get_indexed(7);  }
    187 void _isr_tty_get_8()  { _isr_tty_get_indexed(8);  }
    188 void _isr_tty_get_9()  { _isr_tty_get_indexed(9);  }
    189 void _isr_tty_get_10() { _isr_tty_get_indexed(10); }
    190 void _isr_tty_get_11() { _isr_tty_get_indexed(11); }
    191 void _isr_tty_get_12() { _isr_tty_get_indexed(12); }
    192 void _isr_tty_get_13() { _isr_tty_get_indexed(13); }
    193 void _isr_tty_get_14() { _isr_tty_get_indexed(14); }
    194 void _isr_tty_get_15() { _isr_tty_get_indexed(15); }
    195208
    196209/////////////////////////////////////////////////////////////////////////////////////
    197210// _isr_switch
    198 // This ISR is in charge of context switch.
    199 // It acknowledges the IRQ on TIMER[proc_id] and calls the _ctx_switch() function.
     211// This ISR is in charge of context switch, and handle the IRQs generated by
     212// the "system" timers.
     213// The IRQs can be generated by the MULTI_TIMER component or by the XICU component,
     214// that are distributed in all clusters.
     215// The ISR acknowledges the IRQ and calls the _ctx_switch() function.
    200216/////////////////////////////////////////////////////////////////////////////////////
    201217void _isr_switch()
    202218{
    203     volatile unsigned int *timer_address;
    204     unsigned int proc_id;
    205 
    206     proc_id = _procid();
    207     timer_address = (unsigned int*)&seg_timer_base + (proc_id * TIMER_SPAN);
    208 
    209     timer_address[TIMER_RESETIRQ] = 0; /* reset IRQ */
     219    // get cluster index and proc local index
     220    unsigned int pid        = _procid();
     221    unsigned int loc_id     = pid % NB_PROCS_MAX;
     222    unsigned int cluster_id = pid / NB_PROCS_MAX;
     223
     224#if GIET_USE_XICU
     225
     226    unsigned int* timer_address = // TODO
     227
     228#else
     229
     230    // compute Timer address
     231    unsigned int* timer_address = (unsigned int*)&seg_timer_base +
     232                                  (loc_id * TIMER_SPAN) +
     233                                  (cluster_id * CLUSTER_SPAN);
     234
     235    // reset IRQ
     236    timer_address[TIMER_RESETIRQ] = 0;
     237
     238#endif
     239
     240    // performs the context switch
    210241    _ctx_switch();
    211 }
    212 
     242
     243}
     244
  • soft/giet_vm/sys/irq_handler.h

    r165 r189  
    22#define _IRQ_HANDLER_H
    33
    4 /*
    5  * Interrupt Vector Table (indexed by interrupt index)
    6  *
    7  * 32 entries corresponding to 32 ISR addresses
    8  */
     4enum
     5{
     6    ISR_DEFAULT = 0,
     7    ISR_SWITCH  = 1,
     8    ISR_TTY     = 2,
     9    ISR_DMA     = 3,
     10    ISR_IOC     = 4,
     11    ISR_TIMER   = 5,
     12};
    913
    10 typedef void (*_isr_func_t)(void);
    11 extern _isr_func_t _interrupt_vector[32];
    1214
    13 /*
    14  * Prototypes of the Interrupt Service Routines (ISRs) supported by the GIET.
    15  * - they must be installed in reset.s
    16  */
     15///////////////////////////////////////////////////////////////////////////////
     16// Prototypes of the Interrupt Service Routines (ISRs) supported by the GIET.
     17///////////////////////////////////////////////////////////////////////////////
     18
     19void _irq_demux();
    1720
    1821void _isr_default();
    19 
    20 void _isr_dma_0();
    21 void _isr_dma_1();
    22 void _isr_dma_2();
    23 void _isr_dma_3();
    24 void _isr_dma_4();
    25 void _isr_dma_5();
    26 void _isr_dma_6();
    27 void _isr_dma_7();
    28 
    2922void _isr_ioc();
    30 
    31 void _isr_timer_0();
    32 void _isr_timer_1();
    33 void _isr_timer_2();
    34 void _isr_timer_3();
    35 void _isr_timer_4();
    36 void _isr_timer_5();
    37 void _isr_timer_6();
    38 void _isr_timer_7();
    39 
    40 void _isr_tty_get();
    41 void _isr_tty_get_0();
    42 void _isr_tty_get_1();
    43 void _isr_tty_get_2();
    44 void _isr_tty_get_3();
    45 void _isr_tty_get_4();
    46 void _isr_tty_get_5();
    47 void _isr_tty_get_6();
    48 void _isr_tty_get_7();
    49 void _isr_tty_get_8();
    50 void _isr_tty_get_9();
    51 void _isr_tty_get_10();
    52 void _isr_tty_get_11();
    53 void _isr_tty_get_12();
    54 void _isr_tty_get_13();
    55 void _isr_tty_get_14();
    56 void _isr_tty_get_15();
    57 
     23void _isr_timer( unsigned int channel );
     24void _isr_dma( unsigned int channel );
     25void _isr_tty( unsigned int channel );
    5826void _isr_switch();
    5927
  • soft/giet_vm/sys/kernel_init.c

    r185 r189  
    55// Copyright (c) UPMC-LIP6
    66////////////////////////////////////////////////////////////////////////////////////
    7 // FIXME
    87// The kernel_init.c files is part of the GIET-VM nano-kernel.
    9 // It contains the kernel entry point for the second phase of system initialisation:
    10 // all processors are jumping to _kernel_init, but P[0] is first because other
    11 // processors are blocked until P[0] complete initilisation of task contexts,
    12 // vobjs and peripherals.
    13 // All procs in this phase have their MMU activated, because each processor P[i]
    14 // must initialise registers SP, SR, PTPR and EPC with informations stored
    15 // in _scheduler[i].
     8// It contains the kernel entry point for the last step of system initialisation.
     9// All procs in this phase have their MMU activated, and are running in parallel.
     10// - each processor updates its own scheduler, to replace the ISR index
     11//   by the actual ISR virtual address, and set its own entry in the
     12//   kernel _schedulers_paddr[] array.
     13// - each processor initialises the SP, SR, PTPR, EPC registers, and starts
     14//   its private Timer, before jumping to the user code with an eret.
    1615////////////////////////////////////////////////////////////////////////////////////
    1716
    1817#include <common.h>
     18#include <irq_handler.h>
    1919#include <ctx_handler.h>
    2020#include <sys_handler.h>
     
    2929#include <drivers.h>
    3030
    31 #define in_kinit __attribute__((section (".kinit")))
    32  
    3331///////////////////////////////////////////////////////////////////////////////////
    34 // array of pointers on the page tables
    35 // (both physical and virtual addresses)
     32// Kernel Global variables
    3633///////////////////////////////////////////////////////////////////////////////////
    3734
    38 __attribute__((section (".kdata"))) unsigned int _kernel_ptabs_paddr[GIET_NB_VSPACE_MAX];
    39 __attribute__((section (".kdata"))) unsigned int _kernel_ptabs_vaddr[GIET_NB_VSPACE_MAX];
     35__attribute__((section (".kdata")))
     36page_table_t* _ptabs_paddr[GIET_NB_VSPACE_MAX];
    4037
    41 ///////////////////////////////////////////////////////////////////////////////////
    42 // declarations required to avoid forward references
    43 ///////////////////////////////////////////////////////////////////////////////////
     38__attribute__((section (".kdata")))
     39page_table_t* _ptabs_vaddr[GIET_NB_VSPACE_MAX];
    4440
    45 void    _kernel_ptabs_init(void);
    46 void    _kernel_vobjs_init(void);
    47 void    _kernel_tasks_init(void);
    48 void    _kernel_peripherals_init(void);
    49 void    _kernel_interrupt_vector_init(void);
    50 void    _kernel_start_all_procs(void);
     41__attribute__((section (".kdata")))
     42static_scheduler_t*     _schedulers_paddr[NB_CLUSTERS*NB_PROCS_MAX];
    5143
    5244//////////////////////////////////////////////////////////////////////////////////
    53 // This function is the entry point for the second step of the boot sequence.
     45// This function is the entry point for the last step of the boot sequence.
    5446//////////////////////////////////////////////////////////////////////////////////
    55 in_kinit void _kernel_init()
     47__attribute__((section (".kinit"))) void _kernel_init()
    5648{
    5749    // values to be written in registers
     
    6153    unsigned int        epc_value;
    6254
    63     unsigned int        pid =   _procid();
     55    unsigned int        proc_id    = _procid();
     56    unsigned int    cluster_id = proc_id / NB_PROCS_MAX;
     57    unsigned int    lpid       = proc_id % NB_PROCS_MAX;
    6458
    65     // only processor 0 executes system initialisation
    66     if ( pid == 0 )
     59    // step 1 : Initialise scheduler physical addresses array
     60
     61    // get scheduler physical address from register
     62    static_scheduler_t*         psched = (static_scheduler_t*)_get_sched();
     63    _schedulers_paddr[proc_id]     = psched;
     64
     65#if GIET_DEBUG_INIT
     66_get_lock(&_tty_put_lock);
     67_puts("\n[GIET DEBUG] step 1 for processor ");
     68_putw( proc_id );
     69_puts("\n");
     70_puts("- scheduler pbase = ");
     71_putw( (unsigned int)psched );
     72_puts("\n");
     73_release_lock(&_tty_put_lock);
     74#endif
     75
     76    // step 2 : compute and set ICU mask
     77    unsigned int irq_id;
     78    unsigned int mask = 0;
     79    for ( irq_id = 0 ; irq_id < 32 ; irq_id++ )
    6780    {
    68         _kernel_ptabs_init();
    69         /* must be called after the initialisation of ptabs */
    70         _kernel_vobjs_init();
    71         _kernel_tasks_init();
    72         _kernel_interrupt_vector_init();
    73         _kernel_peripherals_init();
    74         _kernel_start_all_procs();
     81        unsigned int entry   = _get_interrupt_vector_entry(irq_id);
     82        if ( entry ) mask = mask | 0x1<< irq_id;
    7583    }
     84    _icu_write( cluster_id,
     85                lpid,
     86                ICU_MASK_SET,
     87                mask );
     88   
     89#if GIET_DEBUG_INIT
     90_get_lock(&_tty_put_lock);
     91_puts("\n[GIET DEBUG] step 2 for processor ");
     92_putw( proc_id );
     93_puts("\n");
     94_puts("- ICU mask = ");
     95_putw( mask );
     96_puts("\n");
     97_release_lock(&_tty_put_lock);
     98#endif
    7699
    77     // each processor initialises it's SP, SR, PTPR, and EPC registers
    78     // from values defined in _scheduler[pid], starts it's private
    79     // context switch timer (if there is more than one task allocated)
    80     // and jumps to user code.
    81     // It does nothing, and keep idle if no task allocated.
    82100
    83     static_scheduler_t*  sched = &_scheduler[pid];
     101    // step 3 : TODO initialise page table addresse arrays
    84102
    85     if ( sched->tasks )         // at leat one task allocated
     103
     104    // step 4 : start TICK timer if more than one task
     105    unsigned int tasks = _get_tasks_number();
     106    if ( tasks > 1 )
     107    {
     108        unsigned int period     = GIET_TICK_VALUE;
     109        unsigned int mode       = 0x3;
     110        _timer_access( 0,                       // write access
     111                       cluster_id,
     112                       proc_id,
     113                       TIMER_PERIOD,
     114                       &period );
     115        _timer_access( 0,                       // write access
     116                       cluster_id,
     117                       proc_id,
     118                       TIMER_MODE,
     119                       &mode );
     120       
     121#if GIET_DEBUG_INIT
     122_get_lock(&_tty_put_lock);
     123_puts("\n[GIET DEBUG] Step 4 for processor ");
     124_putw( proc_id );
     125_puts("\n");
     126_puts("- TICK period = ");
     127_putd( period );
     128_puts("\n");
     129_release_lock(&_tty_put_lock);
     130#endif
     131   
     132    }
     133
     134    // step 5 : each processor initialises SP, SR, PTPR, EPC, registers
     135    //          with the values corresponding to the first allocated task,
     136    //          It does nothing, and keep idle if no task allocated.
     137
     138    if ( tasks )                // at leat one task allocated
    86139    {
    87140        // initialise registers
    88         sp_value   = sched->context[0][CTX_SP_ID];
    89         sr_value   = sched->context[0][CTX_SR_ID];
    90         ptpr_value = sched->context[0][CTX_PTPR_ID];
    91         epc_value  = sched->context[0][CTX_EPC_ID];
     141        sp_value   = _get_current_context_slot(CTX_SP_ID);
     142        sr_value   = _get_current_context_slot(CTX_SR_ID);
     143        ptpr_value = _get_current_context_slot(CTX_PTPR_ID);
     144        epc_value  = _get_current_context_slot(CTX_EPC_ID);
    92145
    93         // start TICK timer
    94         if ( sched->tasks > 1 )
    95         {
    96             unsigned int cluster_id = pid / NB_PROCS;
    97             unsigned int proc_id    = pid % NB_PROCS;
    98            _timer_write( cluster_id, proc_id, TIMER_PERIOD, GIET_TICK_VALUE );
    99            _timer_write( cluster_id, proc_id, TIMER_MODE  , 0x3 );
    100         }
     146#if GIET_DEBUG_INIT
     147_get_lock(&_tty_put_lock);
     148_puts("\n[GIET DEBUG] step 5 for processor ");
     149_putw( proc_id );
     150_puts("\n");
     151_puts("- sp   = ");
     152_putw( sp_value );
     153_puts("\n");
     154_puts("- sr   = ");
     155_putw( sr_value );
     156_puts("\n");
     157_puts("- ptpr = ");
     158_putw( ptpr_value<<13 );
     159_puts("\n");
     160_puts("- epc  = ");
     161_putw( epc_value );
     162_puts("\n");
     163_release_lock(&_tty_put_lock);
     164#endif
    101165    }
    102166    else                                        // no task allocated
     
    104168        _get_lock( &_tty_put_lock );
    105169        _puts("\n No task allocated to processor ");
    106         _putw( pid );
     170        _putw( proc_id );
    107171        _puts(" => keep idle\n");
    108172        _release_lock ( &_tty_put_lock );
     
    117181    }
    118182
     183    // set critical registers and jump to user code
    119184    asm volatile (
    120185       "move    $29,    %0              \n"             /* SP <= ctx[CTX_SP_ID] */
     
    128193
    129194} // end _kernel_init()
    130 
    131 //////////////////////////////////////////////////////////////////////////////////
    132 // This function wakeup all processors.
    133 // It should be executed by P[0] when the kernel initialisation is done.
    134 //////////////////////////////////////////////////////////////////////////////////
    135 in_kinit void _kernel_start_all_procs()
    136 {
    137     mapping_header_t*   header = (mapping_header_t*)&seg_mapping_base; 
    138 
    139     _puts("\n[INIT] Starting parallel execution at cycle : ");
    140     _putw( _proctime() );
    141     _puts("\n");
    142 
    143     header->signature = OUT_MAPPING_SIGNATURE;
    144 }
    145 
    146 //////////////////////////////////////////////////////////////////////////////////
    147 // _eret()
    148 // The address of this function is used to initialise the return address (RA)
    149 // in all task contexts (when the task has never been executed.
    150 //////////////////////////////////////////////////////////////////////////////////
    151 in_kinit void _eret()
    152 {
    153     asm volatile("eret \n"
    154                  "nop");
    155 }
    156 
    157 ///////////////////////////////////////////////////////////////////////////////
    158 // used to access user space
    159 ///////////////////////////////////////////////////////////////////////////////
    160 void _set_ptpr(unsigned int vspace_id)
    161 {
    162         unsigned int ptpr = ((unsigned int)_kernel_ptabs_paddr[vspace_id]) >> 13;
    163         asm volatile("mtc2 %0, $0"::"r"(ptpr));
    164 }
    165 
    166 ///////////////////////////////////////////////////////////////////////////////
    167 // This function initialises the _kernel_ptabs_paddr[] array indexed by the vspace_id,
    168 // and containing the base addresses of all page tables.
    169 // This _kernel_ptabs_paddr[] array is used to initialise the task contexts.
    170 ///////////////////////////////////////////////////////////////////////////////
    171 in_kinit void _kernel_ptabs_init()
    172 {
    173     mapping_header_t*   header  = (mapping_header_t*)&seg_mapping_base; 
    174     mapping_vspace_t*   vspace  = _get_vspace_base( header );     
    175     mapping_vobj_t*     vobj    = _get_vobj_base( header );
    176 
    177     unsigned int        vspace_id; 
    178     unsigned int        vobj_id;
    179 
    180     // loop on the vspaces
    181     for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
    182     {
    183         char ptab_found = 0;
    184 
    185 #if INIT_DEBUG_CTX
    186 _puts("[INIT] --- ptabs initialisation in vspace ");
    187 _puts(vspace[vspace_id].name);
    188 _puts("\n");
    189 #endif
    190         // loop on the vobjs and get the ptpr
    191             for(vobj_id= vspace[vspace_id].vobj_offset;
    192                         vobj_id < (vspace[vspace_id].vobj_offset+ vspace[vspace_id].vobjs);
    193                         vobj_id++)
    194             {
    195             if(vobj[vobj_id].type == VOBJ_TYPE_PTAB)
    196             {
    197                 if( ptab_found )
    198                 {
    199                     _puts("\n[INIT ERROR] Only one PTAB for by vspace ");
    200                     _putw( vspace_id );
    201                     _exit();
    202                 }
    203 
    204                 ptab_found = 1;
    205                 _kernel_ptabs_paddr[vspace_id] = vobj[vobj_id].paddr;
    206                 _kernel_ptabs_vaddr[vspace_id] = vobj[vobj_id].vaddr;
    207 
    208 #if INIT_DEBUG_CTX
    209 _puts("[INIT]   PTAB address = ");
    210 _putw(_kernel_ptabs_paddr[vspace_id]);
    211 _puts("\n");
    212 #endif
    213             }
    214 
    215         }
    216 
    217         if( !ptab_found )
    218         {
    219             _puts("\n[INIT ERROR] Missing PTAB for vspace ");
    220             _putw( vspace_id );
    221             _exit();
    222         }
    223     }
    224        
    225     _puts("\n[INIT] Ptabs initialisation completed at cycle : ");
    226     _putw( _proctime() );
    227     _puts("\n");
    228 
    229 } // end kernel_ptabs_init()
    230 
    231 ///////////////////////////////////////////////////////////////////////////////
    232 // This function initializes all private vobjs defined in the vspaces,
    233 // such as mwmr channels, barriers and locks, depending on the vobj type.
    234 // (Most of the vobjs are not known, and not initialised by the compiler).
    235 ///////////////////////////////////////////////////////////////////////////////
    236 in_kinit void _kernel_vobjs_init()
    237 {
    238     mapping_header_t*   header  = (mapping_header_t*)&seg_mapping_base; 
    239     mapping_vspace_t*   vspace  = _get_vspace_base( header );     
    240     mapping_vobj_t*     vobj    = _get_vobj_base( header );
    241 
    242     unsigned int        vspace_id; 
    243     unsigned int        vobj_id;
    244 
    245     // loop on the vspaces
    246     for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
    247     {
    248 
    249 #if INIT_DEBUG_CTX
    250 _puts("[INIT] --- vobjs initialisation in vspace ");
    251 _puts(vspace[vspace_id].name);
    252 _puts("\n");
    253 #endif
    254         /** Set the current vspace ptpr to initialise the vobjs */
    255                 _set_ptpr(vspace_id);
    256 
    257         // loop on the vobjs and get the ptpr
    258             for(vobj_id= vspace[vspace_id].vobj_offset;
    259                         vobj_id < (vspace[vspace_id].vobj_offset+ vspace[vspace_id].vobjs);
    260                         vobj_id++)
    261             {
    262             switch( vobj[vobj_id].type )
    263             {
    264                 case VOBJ_TYPE_PTAB:    // initialise page table pointers array
    265                 {
    266                     break;//already handled
    267                 }
    268                 case VOBJ_TYPE_MWMR:    // storage capacity is (vobj.length/4 - 5) words
    269                         {
    270                     mwmr_channel_t* mwmr = (mwmr_channel_t*)(vobj[vobj_id].vaddr);
    271                     mwmr->ptw   = 0;
    272                     mwmr->ptr   = 0;
    273                     mwmr->sts   = 0;
    274                     mwmr->depth = ((vobj[vobj_id].length>>2) - 6);//6= number of entry in the strucure
    275                     mwmr->width = vobj[vobj_id].init;
    276                     mwmr->lock  = 0;
    277 #if INIT_DEBUG_CTX
    278 _puts("[INIT]   MWMR channel ");
    279 _puts( vobj[vobj_id].name);
    280 _puts(" / depth = ");
    281 _putw( mwmr->depth );
    282 _puts("\n");
    283 #endif
    284                     break;
    285                 }
    286                 case VOBJ_TYPE_ELF:             // initialisation done by the loader
    287                 {
    288 
    289 #if INIT_DEBUG_CTX
    290 _puts("[INIT]   ELF section ");
    291 _puts( vobj[vobj_id].name);
    292 _puts(" / length = ");
    293 _putw( vobj[vobj_id].length );
    294 _puts("\n");
    295 #endif
    296                      break;
    297                 }
    298                 case VOBJ_TYPE_BARRIER: // init is the number of participants
    299                 {
    300                     giet_barrier_t* barrier = (giet_barrier_t*)(vobj[vobj_id].vaddr);
    301                     barrier->count = 0;
    302                     barrier->init  = vobj[vobj_id].init;
    303 #if INIT_DEBUG_CTX
    304 _puts("   BARRIER ");
    305 _puts( vobj[vobj_id].name);
    306 _puts(" / init_value = ");
    307 _putw( barrier->init );
    308 _puts("\n");
    309 #endif
    310                     break;
    311                 }
    312                 case VOBJ_TYPE_LOCK:    // init is "not taken"
    313                 {
    314                     unsigned int* lock = (unsigned int*)(vobj[vobj_id].vaddr);
    315                     *lock = 0;
    316 #if INIT_DEBUG_CTX
    317 _puts("   LOCK ");
    318 _puts( vobj[vobj_id].name);
    319 _puts("\n");
    320 #endif
    321                     break;
    322                 }
    323                 case VOBJ_TYPE_BUFFER:  // nothing to do
    324                 {
    325 
    326 #if INIT_DEBUG_CTX
    327 _puts("   BUFFER ");
    328 _puts( vobj[vobj_id].name);
    329 _puts(" / length = ");
    330 _putw( vobj[vobj_id].length );
    331 _puts("\n");
    332 #endif
    333                     break;
    334                 }
    335                 default:
    336                 {
    337                     _puts("\n[INIT ERROR] illegal vobj of name ");
    338                     _puts(vobj[vobj_id].name);
    339                     _puts(" / in vspace = ");
    340                     _puts(vobj[vobj_id].name);
    341                     _puts("\n ");
    342                     _exit();
    343                 }
    344             } // end switch type
    345         } // end loop on vobjs
    346     } // end loop on vspaces
    347 
    348     _puts("\n[INIT] Vobjs initialisation completed at cycle : ");
    349     _putw( _proctime() );
    350     _puts("\n");
    351 
    352 } // end kernel_vobjs_init()
    353 
    354 ///////////////////////////////////////////////////////////////////////////////
    355 // This function maps a given task, defined in a given vspace
    356 // on the processor allocated in the mapping_info structure,
    357 // and initialises the task context.
    358 // There is one scheduler per processor, and processor can be shared
    359 // by several applications running in different vspaces.
    360 // There is one private context array handled by each scheduler.
    361 //
    362 // The following values must be initialised in all task contexts:
    363 // - sp     stack pointer = stack_base + stack_length
    364 // - ra     return address = &_eret
    365 // - epc    start address = start_vector[task->startid]
    366 // - sr     status register = OxFF13
    367 // - tty    TTY terminal index (global index)
    368 // - fb     FB_DMA channel index (global index)
    369 // - ptpr   page table base address / 8K
    370 // - mode   mmu_mode = 0xF (TLBs and caches activated)
    371 // - ptab   page table virtual address
    372 ////////////////////////////////////////////////////////////////////////////////
    373 in_kinit void _task_map( unsigned int   task_id,    // global index
    374                                          unsigned int   vspace_id,  // global index
    375                          unsigned int   tty_id,         // TTY index
    376                          unsigned int   fbdma_id )  // FBDMA index
    377 {
    378     mapping_header_t*   header = (mapping_header_t*)&seg_mapping_base; 
    379 
    380     mapping_task_t*     task   = _get_task_base(header);
    381     mapping_vspace_t*   vspace = _get_vspace_base(header);
    382     mapping_vobj_t*     vobj   = _get_vobj_base( header );
    383 
    384     /** Set the current vspace ptpr before acessing the memory */
    385     _set_ptpr(vspace_id);
    386    
    387     // values to be initialised in task context
    388     unsigned int                ra   = (unsigned int)&_eret;
    389     unsigned int                sr   = 0x0000FF13;
    390     unsigned int                tty  = tty_id;
    391     unsigned int                fb   = fbdma_id;         
    392     unsigned int                ptpr = _kernel_ptabs_paddr[vspace_id] >> 13;
    393     unsigned int                ptab = _kernel_ptabs_vaddr[vspace_id];
    394     unsigned int                mode = 0xF;
    395     unsigned int                sp;
    396     unsigned int                epc;     
    397 
    398     // EPC : Get the (virtual) base address of the start_vector containing
    399     // the start addresses for all tasks defined in a vspace.
    400     mapping_vobj_t* vobj_data = &vobj[vspace[vspace_id].vobj_offset +
    401                                       vspace[vspace_id].start_offset];
    402     unsigned int* start_vector = (unsigned int*)vobj_data->vaddr;
    403     epc  = start_vector[task[task_id].startid];
    404 
    405     // SP :  Get the vobj containing the stack
    406     unsigned int vobj_id = task[task_id].vobjlocid + vspace[vspace_id].vobj_offset;
    407     sp = vobj[vobj_id].vaddr + vobj[vobj_id].length;
    408 
    409     // compute global processor index
    410     unsigned int proc_id = task[task_id].clusterid * NB_PROCS + task[task_id].proclocid;
    411 
    412     // compute and check local task index
    413     unsigned int ltid = _scheduler[proc_id].tasks;
    414     if ( ltid >= GIET_NB_TASKS_MAX )
    415     {
    416         _puts("\n[INIT ERROR] : too much tasks allocated to processor ");
    417         _putw( proc_id );
    418         _puts("\n");
    419         _exit();
    420     }
    421    
    422     // update number of tasks allocated to scheduler
    423     _scheduler[proc_id].tasks = ltid + 1;
    424 
    425     // initializes the task context
    426     _scheduler[proc_id].context[ltid][CTX_SR_ID]    = sr;
    427     _scheduler[proc_id].context[ltid][CTX_SP_ID]    = sp;
    428     _scheduler[proc_id].context[ltid][CTX_RA_ID]    = ra;
    429     _scheduler[proc_id].context[ltid][CTX_EPC_ID]   = epc;
    430     _scheduler[proc_id].context[ltid][CTX_PTPR_ID]  = ptpr;
    431     _scheduler[proc_id].context[ltid][CTX_MODE_ID]  = mode;
    432     _scheduler[proc_id].context[ltid][CTX_TTY_ID]   = tty;
    433         _scheduler[proc_id].context[ltid][CTX_FBDMA_ID] = fb;
    434     _scheduler[proc_id].context[ltid][CTX_PTAB_ID]  = ptab;
    435     _scheduler[proc_id].context[ltid][CTX_TASK_ID]  = task_id;
    436    
    437 #if INIT_DEBUG_CTX
    438 _puts("Task ");
    439 _puts( task[task_id].name );
    440 _puts(" allocated to processor ");
    441 _putw( proc_id );
    442 _puts(" / ltid = ");
    443 _putw( ltid );
    444 _puts("\n");
    445 
    446 _puts("  - SR          = ");
    447 _putw( sr );
    448 _puts("  saved at ");
    449 _putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_SR_ID] );
    450 _puts("\n");
    451 
    452 _puts("  - RA          = ");
    453 _putw( ra );
    454 _puts("  saved at ");
    455 _putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_RA_ID] );
    456 _puts("\n");
    457 
    458 _puts("  - SP          = ");
    459 _putw( sp );
    460 _puts("  saved at ");
    461 _putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_SP_ID] );
    462 _puts("\n");
    463 
    464 _puts("  - EPC         = ");
    465 _putw( epc );
    466 _puts("  saved at ");
    467 _putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_EPC_ID] );
    468 _puts("\n");
    469 
    470 _puts("  - PTPR        = ");
    471 _putw( ptpr<<13 );
    472 _puts("  saved at ");
    473 _putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_PTPR_ID] );
    474 _puts("\n");
    475 
    476 _puts("  - TTY         = ");
    477 _putw( tty );
    478 _puts("  saved at ");
    479 _putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_TTY_ID] );
    480 _puts("\n");
    481 
    482 _puts("  - FB          = ");
    483 _putw( fb );
    484 _puts("  saved at ");
    485 _putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_FBDMA_ID] );
    486 _puts("\n");
    487 
    488 _puts("  - PTAB        = ");
    489 _putw( ptab );
    490 _puts("  saved at ");
    491 _putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_PTAB_ID] );
    492 _puts("\n");
    493 #endif
    494 
    495 } // end _task_map()
    496 
    497 ///////////////////////////////////////////////////////////////////////////////
    498 // This function initialises all task contexts and processors schedulers.
    499 // It sets the default values for all schedulers (tasks <= 0, current <= 0).
    500 // Finally, it scan all tasks in all vspaces to initialise the schedulers,
    501 // and the tasks contexts, as defined in the mapping_info data structure.
    502 // A global TTY index and a global FB channel are allocated if required.
    503 // TTY[0] is reserved for the kernel.
    504 ///////////////////////////////////////////////////////////////////////////////
    505 in_kinit void _kernel_tasks_init()
    506 {
    507     mapping_header_t*   header  = (mapping_header_t*)&seg_mapping_base; 
    508     mapping_cluster_t*  cluster = _get_cluster_base( header );
    509     mapping_vspace_t*   vspace  = _get_vspace_base( header );     
    510     mapping_task_t*     task    = _get_task_base( header );
    511 
    512     unsigned int        base_tty_id = 1;     // TTY index allocator
    513     unsigned int        base_fb_id  = 0;     // FB channel index allocator
    514 
    515     unsigned int        cluster_id; 
    516     unsigned int        proc_id; 
    517     unsigned int        vspace_id; 
    518     unsigned int        task_id;
    519 
    520     // initialise the schedulers (not done by the compiler)
    521     for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
    522     {
    523         for ( proc_id = 0 ; proc_id < cluster[cluster_id].procs ; proc_id++ )
    524         {
    525             if ( proc_id >= NB_PROCS )
    526             {
    527                 _puts("\n[INIT ERROR] The number of processors in cluster ");
    528                 _putw( cluster_id );
    529                 _puts(" is larger than NB_PROCS \n");
    530                 _exit();
    531             }
    532             _scheduler[cluster_id*NB_PROCS+proc_id].tasks   = 0;
    533             _scheduler[cluster_id*NB_PROCS+proc_id].current = 0;
    534         }
    535     }
    536 
    537     // loop on the virtual spaces
    538     for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
    539     {
    540 
    541 #if INIT_DEBUG_CTX
    542 _puts("\n[INIT] mapping tasks in vspace ");
    543 _puts(vspace[vspace_id].name);
    544 _puts("\n");
    545 #endif
    546         // loop on the tasks
    547         for ( task_id = vspace[vspace_id].task_offset ;
    548               task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks) ;
    549               task_id++ )
    550         {
    551             unsigned int        tty_id = 0xFFFFFFFF;
    552             unsigned int        fb_id  = 0xFFFFFFFF;
    553             if ( task[task_id].use_tty )
    554             {
    555                 tty_id = base_tty_id;
    556                 base_tty_id++;
    557             }
    558             if ( task[task_id].use_fb  )
    559             {
    560                 fb_id = base_fb_id;
    561                 base_fb_id++;
    562             }
    563             _task_map( task_id,                         // global task index
    564                        vspace_id,                       // vspace index
    565                        tty_id,                          // global tty index
    566                        fb_id );                         // global fbdma index
    567         } // end loop on tasks
    568     } // end oop on vspaces
    569 
    570     _puts("\n[INIT] Task Contexts initialisation completed at cycle ");
    571     _putw( _proctime() );
    572     _puts("\n");
    573 
    574 #if INIT_DEBUG_CTX
    575 for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
    576 {
    577     _puts("\nCluster ");
    578     _putw( cluster_id );
    579     _puts("\n");
    580     for ( proc_id = 0 ; proc_id < cluster[cluster_id].procs ; proc_id++ )
    581     {
    582         unsigned int ltid;              // local task index
    583         unsigned int gtid;              // global task index
    584         unsigned int pid = cluster_id * NB_PROCS + proc_id;
    585        
    586         _puts(" - processor ");
    587         _putw( pid );
    588         _puts("\n");
    589         for ( ltid = 0 ; ltid < _scheduler[pid].tasks ; ltid++ )
    590         {
    591             gtid = _scheduler[pid].context[ltid][CTX_TASK_ID];
    592             _puts("    task : ");
    593             _puts( task[gtid].name );
    594             _puts("\n");
    595         }
    596     }
    597 }
    598 #endif
    599 
    600 } // end _kernel_task_init()
    601 
    602 ////////////////////////////////////////////////////////////////////////////////
    603 // This function intializes the external periherals such as the IOB component
    604 // (I/O bridge, containing the IOMMU, the IOC (external disk controller),
    605 // the NIC (external network controller), the FBDMA (frame buffer controller),
    606 ////////////////////////////////////////////////////////////////////////////////
    607 in_kinit void _kernel_peripherals_init()
    608 {
    609     /////////////////////
    610     // IOC peripheral
    611     // we simply activate the IOC interrupts...
    612     if ( NB_IOC )
    613     {
    614         unsigned int*   ioc_address = (unsigned int*)&seg_ioc_base;
    615         ioc_address[BLOCK_DEVICE_IRQ_ENABLE] = 1;
    616     }
    617    
    618     /////////////////////
    619     // FBDMA peripheral
    620     // we simply activate the DMA interrupts...
    621     if ( NB_DMAS )
    622     {
    623         unsigned int*   dma_address = (unsigned int*)&seg_dma_base;
    624         dma_address[DMA_IRQ_DISABLE] = 0;
    625     }
    626 
    627     /////////////////////
    628     // IOB peripheral
    629     // must be initialised in case of IOMMU
    630     if ( GIET_IOMMU_ACTIVE )
    631     {
    632         unsigned int*   iob_address = (unsigned int*)&seg_iob_base;
    633 
    634         // define IPI address mapping the IOC interrupt ...TODO...
    635 
    636         // set IOMMU page table address
    637         iob_address[IOB_IOMMU_PTPR] = (unsigned int)(&_iommu_ptab);   
    638 
    639         // activate IOMMU
    640         iob_address[IOB_IOMMU_ACTIVE] = 1;   
    641     }
    642 
    643     _puts("\n[INIT] Peripherals initialisation completed at cycle ");
    644     _putw( _proctime() );
    645     _puts("\n");
    646 
    647 } // end _kernel_peripherals_init()
    648 
    649 ////////////////////////////////////////////////////////////////////////////////
    650 // This function intialises the interrupt vector, and initialises
    651 // the ICU mask registers for all processors in all clusters.
    652 // It strongly depends on the actual peripheral hardware wiring.
    653 // In this peculiar version, all clusters are identical,
    654 // the number of processors per cluster cannot be larger than 8.
    655 // Processor 0 handle all interrupts corresponding to TTYs, DMAs and IOC
    656 // (ICU inputs from from IRQ[8] to IRQ[31]). Only the 8 TIMER interrupts
    657 // (ICU iputs IRQ[0] to IRQ[7]), that are used for context switching
    658 // are distributed to the 8 processors.
    659 ////////////////////////////////////////////////////////////////////////////////
    660 in_kinit void _kernel_interrupt_vector_init()
    661 {
    662     mapping_header_t*   header  = (mapping_header_t*)&seg_mapping_base; 
    663     mapping_cluster_t*  cluster = _get_cluster_base( header );
    664 
    665     unsigned int cluster_id;
    666     unsigned int proc_id;
    667 
    668     // ICU mask values (up to 8 processors per cluster)
    669     unsigned int icu_mask[8] = { 0xFFFFFF01,
    670                                  0x00000002,
    671                                  0x00000004,
    672                                  0x00000008,
    673                                  0x00000010,
    674                                  0x00000020,
    675                                  0x00000040,
    676                                  0x00000080 };
    677 
    678     // initialise ICUs for each processor in each cluster
    679     for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
    680     {
    681         for ( proc_id = 0 ; proc_id < cluster[cluster_id].procs ; proc_id++ )
    682         {
    683             _icu_write( cluster_id, proc_id, ICU_MASK_SET, icu_mask[proc_id] );
    684         }
    685     }
    686 
    687     // initialize Interrupt vector
    688 
    689     _interrupt_vector[0]   = &_isr_switch;
    690     _interrupt_vector[1]   = &_isr_switch;
    691     _interrupt_vector[2]   = &_isr_switch;
    692     _interrupt_vector[3]   = &_isr_switch;
    693     _interrupt_vector[4]   = &_isr_switch;
    694     _interrupt_vector[5]   = &_isr_switch;
    695     _interrupt_vector[6]   = &_isr_switch;
    696     _interrupt_vector[7]   = &_isr_switch;
    697 
    698     _interrupt_vector[8]   = &_isr_dma_0;
    699     _interrupt_vector[9]   = &_isr_dma_1;
    700     _interrupt_vector[10]  = &_isr_dma_2;
    701     _interrupt_vector[11]  = &_isr_dma_3;
    702     _interrupt_vector[12]  = &_isr_dma_4;
    703     _interrupt_vector[13]  = &_isr_dma_5;
    704     _interrupt_vector[14]  = &_isr_dma_6;
    705     _interrupt_vector[15]  = &_isr_dma_7;
    706 
    707     _interrupt_vector[16]  = &_isr_tty_get_0;
    708     _interrupt_vector[17]  = &_isr_tty_get_1;
    709     _interrupt_vector[18]  = &_isr_tty_get_2;
    710     _interrupt_vector[19]  = &_isr_tty_get_3;
    711     _interrupt_vector[20]  = &_isr_tty_get_4;
    712     _interrupt_vector[21]  = &_isr_tty_get_5;
    713     _interrupt_vector[22]  = &_isr_tty_get_6;
    714     _interrupt_vector[23]  = &_isr_tty_get_7;
    715     _interrupt_vector[24]  = &_isr_tty_get_8;
    716     _interrupt_vector[25]  = &_isr_tty_get_9;
    717     _interrupt_vector[26]  = &_isr_tty_get_10;
    718     _interrupt_vector[27]  = &_isr_tty_get_11;
    719     _interrupt_vector[28]  = &_isr_tty_get_12;
    720     _interrupt_vector[29]  = &_isr_tty_get_13;
    721     _interrupt_vector[30]  = &_isr_tty_get_14;
    722 
    723     _interrupt_vector[31]  = &_isr_ioc;
    724 
    725     _puts("\n[INIT] Interrupt vector initialisation completed at cycle ");
    726     _putw( _proctime() );
    727     _puts("\n");
    728 
    729 } // end _kernel_interrup_vector_init()
  • soft/giet_vm/sys/mips32_registers.h

    r167 r189  
    5353#define CP0_EPC                 $14
    5454#define CP0_PROCID              $15,1
     55#define CP0_SCHED               $22
    5556
    5657/* CP2 registers */
  • soft/giet_vm/sys/switch.s

    r158 r189  
    11/******************************************************************************
    2 * This function receives two arguments representing addresses of task
    3 * contexts, respectively for the current running task to be descheduled and
    4 * for the next task to be scheduled.
     2* This function receives two arguments that are the current task context
     3* physical addresses and the next task context physical address.
    54******************************************************************************/
    65
     
    1110_task_switch:
    1211
     12    /* desactivate DTLB */
     13    ori         $27,    $0,             0xB
     14    mtc2        $27,    $1                      /* DTLB desactivated */
     15
    1316    /* save _current task context */
    14 
    1517    add     $27,    $4,     $0  /* $27 <= &context[curr_task_id] */
    1618
     
    5860    mfc2    $26,    $0
    5961    sw      $26,    35*4($27)   /* ctx[35] <= PTPR */
    60     mfc2    $26,    $1
    61     sw      $26,    36*4($27)   /* ctx[36] <= MODE */
    6262
    6363    /* restore next task context */
    64 
    6564    add     $27,    $5,     $0  /* $27<= &context[next_task_id] */
    6665
    6766    lw      $26,    35*4($27)
    6867    mtc2    $26,    $0          /* restore PTPR */
    69     lw      $26,    36*4($27)
    70     mtc2    $26,    $1          /* restore MODE */
    7168    lw      $26,    0*4($27)
    7269    mtc0    $26,    $12         /* restore SR */
     
    111108    mtc0    $26,    $13         /* restore CR */
    112109
    113     jr      $31                 /* returns to caller */
     110    /* activate DTLB */
     111    ori         $27,    $0,             0xF
     112    mtc2        $27,    $1     
     113
     114    /* returns to caller */
     115    jr      $31
    114116
    115117    .endfunc
  • soft/giet_vm/sys/sys_handler.c

    r167 r189  
    7575void _exit()
    7676{
     77/*
    7778    unsigned int date    = _proctime();
     79
    7880    unsigned int proc_id = _procid();
    79     unsigned int task_id = _scheduler[proc_id].current;
     81
     82    unsigned int task_id = _get_current_task_id();
    8083
    8184     // print death message
     85    _get_lock(&_tty_put_lock);
    8286    _puts("\n\n!!! Exit task ");
    8387    _putw( task_id );
     
    8791    _putw( date );
    8892    _puts("\n\n");
    89 
     93    _release_lock(&_tty_put_lock);
     94*/
     95   
    9096    /* infinite loop */
    9197    while (1) asm volatile("nop");
  • soft/giet_vm/sys/vm_handler.c

    r184 r189  
    118118
    119119        // gets ppn_value and flags_value, after temporary DTLB desactivation
    120         asm volatile (
    121                        "li      $27,    0xFFFFFFFE  \n"     /* Mask for IE bits     */
    122                        "mfc0    $8,     $12         \n"     /* $8 <= SR             */
    123                        "and     $26,    $8,    $27 \n"      /* $26 <= SR && 0xFFFFFFE */
    124                        "mtc0    $26,    $12         \n"     /* disable Interrupts   */
     120        asm volatile ( "li      $27,    0xFFFFFFFE  \n"     /* Mask for IE bits     */
     121                       "mfc0    $26,    $12         \n"     /* save SR              */
     122                       "and     $27,    $26,    $27 \n"
     123                       "mtc0    $27,    $12         \n"     /* disable Interrupts   */
     124
     125                       "li      $27,    0xB         \n"     
     126                       "mtc2    $27,    $1          \n"     /* DTLB unactivated     */
    125127
    126128                       "move    $27,    %2          \n"     /* $27 <= pte2          */
    127                        "li      $26,    0xB         \n"     /* DTLB unactivated     */
    128                        "mtc2    $26,    $1          \n"
    129129                       "lw      %0,     0($27)      \n"     /* read flags           */
    130130                       "lw      %1,     4($27)      \n"     /* read ppn             */
    131                        "li      $26,    0xF         \n"
    132                        "mtc2    $26,    $1          \n"     /* DTLB activated       */
    133131
    134                        "or     $26,     $8,    $0   \n"     /* SR previous state    */
     132                       "li      $27,    0xF         \n"
     133                       "mtc2    $27,    $1          \n"     /* DTLB activated       */
     134
     135                       "mtc0    $26,    $12         \n"     /* restore SR           */
    135136                        :"=r"(flags_value), "=r"(ppn_value)
    136137                        :"r"(pte2)
  • soft/giet_vm/sys/vm_handler.h

    r180 r189  
    5353typedef struct PageTable
    5454{
    55         unsigned int    pt1[PT1_SIZE/4];        // PT1 (index is ix1)
    56         unsigned int    pt2[1][PT2_SIZE/4];     // PT2s (index is 2*ix2)
    57     /*  The number `1` is onmy here to indicate to the compiler that this is a table
    58      ** of two dimension and the actual value is computed dynamically(see boot_handler.c)*/
     55        unsigned int    pt1[PT1_SIZE/4];                      // PT1 (index is ix1)
     56        unsigned int    pt2[GIET_NB_PT2_MAX][PT2_SIZE/4];     // PT2s (index is 2*ix2)
    5957} page_table_t;
    6058
Note: See TracChangeset for help on using the changeset viewer.