Ignore:
Timestamp:
Feb 8, 2015, 12:30:47 PM (10 years ago)
Author:
alain
Message:

1) Introduce a fully parallel procedure for both
page tables ans schedulers initialisation.
2) Introduce support for platforms containing clusters
without processors (as in the tsar_generic_leti).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • soft/giet_vm/giet_boot/boot.c

    r490 r493  
    1 /////////////////////////////////////////////////////////////////////////////////////////
     1///////////////////////////////////////////////////////////////////////////////////////
    22// File     : boot.c
    33// Date     : 01/11/2013
    44// Author   : alain greiner
    55// Copyright (c) UPMC-LIP6
    6 //////////////////////////////////////////////////////////////////////////////////////////
    7 // The boot.c file is part of the GIET-VM nano-kernel.
     6///////////////////////////////////////////////////////////////////////////////////////
     7// The boot.c file contains the bootloader for the GIET-VM static OS. 
    88//
    9 // This nano-kernel has been written for the MIPS32 processor.
     9// This code has been written for the MIPS32 processor.
    1010// The virtual adresses are on 32 bits and use the (unsigned int) type. The
    1111// physicals addresses can have up to 40 bits, and use the  (unsigned long long) type.
    1212// It natively supports clusterised shared memory multi-processors architectures,
    13 // where each processor is identified by a composite index (cluster_xy, local_id),
     13// where each processor is identified by a composite index [x,y,p],
    1414// and where there is one physical memory bank per cluster.
    1515//
    16 // This code, executed in the boot phase by proc[0,0,0], performs the following tasks:
    17 // - load into memory various binary files, from a FAT32 file system,
    18 // - build the various page tables (one page table per vspace)
    19 // - initialize the shedulers (one scheduler per processor)
     16// The boot.elf file is stored on disk and is loaded into memory by proc[0,0,0],
     17// executing the generic preloader (stored in ROM). The boot-loader code itself
     18// is executed in parallel by all proc[x,y,0], and performs the following tasks:
     19// - load into memory various binary files, from a FAT32 file system.
     20// - build the various page tables (one page table per vspace).
     21// - initialize the shedulers (one scheduler per processor).
     22// - initialize the external peripherals.
    2023//
    2124// 1) The binary files to be loaded are:
     
    2326//      mapping directives. It must be stored in the the seg_boot_mapping segment
    2427//      (at address SEG_BOOT_MAPPING_BASE defined in hard_config.h file).
    25 //    - the "sys.elf" file contains the kernel binary code and data.
     28//    - the "kernel.elf" file contains the kernel binary code and data.
    2629//    - the various "application.elf" files.
    2730//
    28 // 2) The map.bin file contains the binary representation of the map.xml file defining:
     31// 2) The "map.bin" file contains the C binary structure defining:
    2932//    - the hardware architecture: number of clusters, number or processors,
    3033//      size of the memory segments, and peripherals in each cluster.
     
    4144//      of the software objects (vsegs) on the physical memory banks (psegs).
    4245//
    43 //    The max number of vspaces (GIET_NB_VSPACE_MAX) is a configuration parameter.
     46//    The max number of vspaces (GIET_NB_VSPACE_MAX) is a configuration parameter,
     47//    and - for each application - the tasks are statically allocateded on procesors.
    4448//    The page table are statically build in the boot phase, and they do not
    4549//    change during execution.
     
    5256//    A PT2 is indexed the ix2 field (9 bits) of the VPN. Each entry is a double word.
    5357//    The first word contains the flags, the second word contains the PPN.
    54 //
    55 //    When this is required in the mapping, the page tables can be replicated
    56 //    in all clusters.
     58//    The page tables are distributed/replicated in all clusters.
    5759///////////////////////////////////////////////////////////////////////////////////////
    5860// Implementation Notes:
    5961//
    6062// 1) The cluster_id variable is a linear index in the mapping_info array of clusters.
    61 //    We use the cluster_xy variable for the tological index = x << Y_WIDTH + y
     63//    The cluster_xy variable is the tological index = x << Y_WIDTH + y
    6264//
     65// 2) We set the _tty0_boot_mode variable to force the _printf() function to use
     66//    the tty0_spin_lock for exclusive access to TTY0.
    6367///////////////////////////////////////////////////////////////////////////////////////
    6468
     
    6771#include <mapping_info.h>
    6872#include <kernel_malloc.h>
    69 #include <barrier.h>
    7073#include <memspace.h>
    7174#include <tty_driver.h>
     
    8689#include <utils.h>
    8790#include <tty0.h>
    88 #include <locks.h>
     91#include <kernel_locks.h>
     92#include <kernel_barriers.h>
    8993#include <elf-types.h>
    9094#include <fat32.h>
     
    131135
    132136// FAT internal representation for boot code 
    133 __attribute__((section (".bootdata")))
    134 fat32_fs_t             fat   __attribute__((aligned(512)));
     137__attribute__((section(".kdata")))
     138fat32_fs_t          fat   __attribute__((aligned(512)));
    135139
    136140// Temporaty buffer used to load one complete .elf file 
    137 __attribute__((section (".bootdata")))
    138 char                   boot_elf_buffer[GIET_ELF_BUFFER_SIZE] __attribute__((aligned(512)));
     141__attribute__((section(".kdata")))
     142char                boot_elf_buffer[GIET_ELF_BUFFER_SIZE] __attribute__((aligned(512)));
    139143
    140144// Physical memory allocators array (one per cluster)
    141 __attribute__((section (".bootdata")))
    142 pmem_alloc_t           boot_pmem_alloc[X_SIZE][Y_SIZE];
     145__attribute__((section(".kdata")))
     146pmem_alloc_t        boot_pmem_alloc[X_SIZE][Y_SIZE];
    143147
    144148// Distributed kernel heap (one per cluster)
    145 __attribute__((section (".bootdata")))
    146 kernel_heap_t          kernel_heap[X_SIZE][Y_SIZE];
     149// __attribute__((section(".kdata")))
     150// kernel_heap_t       kernel_heap[X_SIZE][Y_SIZE];
    147151
    148152// Schedulers virtual base addresses array (one per processor)
    149 __attribute__((section (".bootdata")))
    150 static_scheduler_t*    _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX];
     153__attribute__((section(".kdata")))
     154static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX];
    151155
    152156// Page tables virtual base addresses array (one per vspace)
    153 __attribute__((section (".bootdata")))
    154 unsigned int           _ptabs_vaddr[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
     157__attribute__((section(".kdata")))
     158unsigned int        _ptabs_vaddr[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
    155159
    156160// Page tables physical base addresses (one per vspace and per cluster)
    157 __attribute__((section (".bootdata")))
    158 paddr_t                _ptabs_paddr[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
     161__attribute__((section(".kdata")))
     162paddr_t             _ptabs_paddr[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
    159163
    160164// Page tables pt2 allocators (one per vspace and per cluster)
    161 __attribute__((section (".bootdata")))
    162 unsigned int           _ptabs_next_pt2[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
     165__attribute__((section(".kdata")))
     166unsigned int        _ptabs_next_pt2[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
    163167
    164168// Page tables max_pt2  (same value for all page tables)
    165 __attribute__((section (".bootdata")))
    166 unsigned int           _ptabs_max_pt2;
    167 
    168 __attribute__((section (".bootdata")))
    169 //volatile struct _boot_init_ok {
    170 //    unsigned int value;
    171 //}__attribute__((aligned(64)));
    172 //struct _boot_init_ok boot_init_ok = {0};
    173 volatile unsigned int boot_init_ok = 0;
    174 
    175 __attribute__((section (".bootdata")))
    176 volatile _giet_lock_t lock_tty;
    177 
    178 __attribute__((section (".bootdata")))
    179 volatile _giet_barrier_t barrier_boot;
    180 
    181 __attribute__((section (".bootdata")))
    182 volatile _giet_lock_t lock_next_pt2[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
    183 
    184 // Global variables for TTY
    185 __attribute__((section (".bootdata")))
    186 sbt_lock_t             _tty_tx_lock[NB_TTY_CHANNELS]   __attribute__((aligned(64)));
    187 
    188 __attribute__((section (".bootdata")))
    189 unsigned int           _tty_rx_full[NB_TTY_CHANNELS];
    190 #if BOOT_DEBUG_MAPPING
    191 unsigned int  word;
    192 unsigned int  line;
    193 unsigned int* pointer = (unsigned int*)SEG_BOOT_MAPPING_BASE;
    194 _puts("\n[BOOT] First block of mapping");
    195 for ( line = 0 ; line < 8 ; line++ )
    196 {
    197     for ( word = 0 ; word < 8 ; word++ )
    198     {
    199         _puts(" | ");
    200         _putx( *(pointer + word) );
    201     }
    202     _puts(" |\n");
    203     pointer = pointer + 8;
    204 }
    205 #endif
    206 
    207 __attribute__((section (".bootdata")))
    208 unsigned int           _tty_rx_buf[NB_TTY_CHANNELS];
     169__attribute__((section(".kdata")))
     170unsigned int        _ptabs_max_pt2;
     171
     172// WTI channel allocator (one per cluster)
     173__attribute__((section(".kdata")))
     174unsigned int        _wti_channel_alloc[X_SIZE][Y_SIZE];
     175
     176// boot code uses a spin lock to protect TTY0
     177__attribute__((section(".kdata")))
     178unsigned int        _tty0_boot_mode = 1;
     179
     180__attribute__((section(".kdata")))
     181spin_lock_t         _ptabs_spin_lock[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
     182
     183// barrier used by boot code for parallel execution
     184__attribute__((section(".kdata")))
     185simple_barrier_t    _barrier_all_clusters;
     186
     187// this variable is defined in the tty0.c file
     188extern spin_lock_t  _tty0_spin_lock;
    209189
    210190//////////////////////////////////////////////////////////////////////////////
     
    212192// by the vspace_id argument, and the (x,y) coordinates.
    213193// It updates only the first level PT1.
     194// As each vseg is mapped by a different processor, the PT1 entry cannot
     195// be concurrently accessed, and we don't need to take any lock.
    214196//////////////////////////////////////////////////////////////////////////////
    215197void boot_add_pte1( unsigned int vspace_id,
     
    220202                    unsigned int ppn )       // 28 bits right-justified
    221203{
    222 
    223 #if (BOOT_DEBUG_PT > 1)
    224 _get_lock(&lock_tty);
    225 _puts(" - PTE1 in PTAB[");
    226 _putd( vspace_id );
    227 _puts(",");
    228 _putd( x );
    229 _puts(",");
    230 _putd( y );
    231 _puts("] : vpn = ");
    232 _putx( vpn );
    233 _puts(" / ppn = ");
    234 _putx( ppn );
    235 _puts(" / flags = ");
    236 _putx( flags );
    237 _puts("\n");
    238 _release_lock(&lock_tty);
    239 #endif
    240 
    241     unsigned int procid     = _get_procid();
    242     unsigned int x_cluster  = (procid >> (Y_WIDTH + P_WIDTH)) & ((1<<X_WIDTH)-1);
    243     unsigned int y_cluster  = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
    244 
    245204    // compute index in PT1
    246205    unsigned int    ix1 = vpn >> 9;         // 11 bits for ix1
    247206
    248207    // get page table physical base address
    249     paddr_t         pt1_pbase = _ptabs_paddr[vspace_id][x][y];
    250 
    251     // check pt1_base
     208    paddr_t  pt1_pbase = _ptabs_paddr[vspace_id][x][y];
     209
    252210    if ( pt1_pbase == 0 )
    253211    {
    254         _get_lock(&lock_tty);
    255         _puts("\n[BOOT ERROR] in boot_add_pte1() : illegal pbase address for PTAB[");
    256         _putd( vspace_id );
    257         _puts(",");
    258         _putd( x );
    259         _puts(",");
    260         _putd( y );
    261         _puts("]");
    262         _puts(" in cluster[");
    263         _putd(x_cluster);
    264         _puts(",");
    265         _putd(y_cluster);
    266         _puts("]\n");
    267         _release_lock(&lock_tty);
     212        _printf("\n[BOOT ERROR] in boot_add_pte1() : no PTAB in cluster[%d,%d]"
     213                    " containing processors\n", x , y );
    268214        _exit();
    269215    }
     
    277223    _physical_write( pt1_pbase + 4*ix1, pte1 );
    278224
    279 #if (BOOT_DEBUG_PT > 1 )
    280 _get_lock(&lock_tty);
    281 _puts(" - Write pte1 ");
    282 _putx( pte1 );
    283 _puts(" in paddr ");
    284 _putl( pt1_pbase + 4*ix1 );
    285 _puts(" in cluster[");
    286 _putd(x_cluster);
    287 _puts(",");
    288 _putd(y_cluster);
    289 _puts("]\n");
    290 _puts("\n");
    291 _release_lock(&lock_tty);
    292 #endif
     225    asm volatile ("sync");
    293226
    294227}   // end boot_add_pte1()
     
    300233// As the set of PT2s is implemented as a fixed size array (no dynamic
    301234// allocation), this function checks a possible overflow of the PT2 array.
     235// As a given entry in PT1 can be shared by several vsegs, mapped by
     236// different processors, we need to take the lock protecting PTAB[v][x]y].
    302237//////////////////////////////////////////////////////////////////////////////
    303238void boot_add_pte2( unsigned int vspace_id,
     
    308243                    unsigned int ppn )       // 28 bits right-justified
    309244{
    310 
    311 #if (BOOT_DEBUG_PT > 1)
    312 _get_lock(&lock_tty);
    313 _puts(" - PTE2 in PTAB[");
    314 _putd( vspace_id );
    315 _puts(",");
    316 _putd( x );
    317 _puts(",");
    318 _putd( y );
    319 _puts("] : vpn = ");
    320 _putx( vpn );
    321 _puts(" / ppn = ");
    322 _putx( ppn );
    323 _puts(" / flags = ");
    324 _putx( flags );
    325 _puts("\n");
    326 _release_lock(&lock_tty);
    327 #endif
    328 
    329245    unsigned int ix1;
    330246    unsigned int ix2;
     
    337253    ix2 = vpn & 0x1FF;          //  9 bits for ix2
    338254
    339     // get page table physical base address and size
     255    // get page table physical base address
    340256    paddr_t      pt1_pbase = _ptabs_paddr[vspace_id][x][y];
    341257
    342     // check pt1_base
    343258    if ( pt1_pbase == 0 )
    344259    {
    345         _get_lock(&lock_tty);
    346         _puts("\n[BOOT ERROR] in boot_add_pte2() : PTAB[");
    347         _putd( vspace_id );
    348         _puts(",");
    349         _putd( x );
    350         _puts(",");
    351         _putd( y );
    352         _puts("] undefined\n");
    353         _release_lock(&lock_tty);
     260        _printf("\n[BOOT ERROR] in boot_add_pte2() : no PTAB for vspace %d "
     261                "in cluster[%d,%d]\n", vspace_id , x , y );
    354262        _exit();
    355263    }
    356264
     265    // get lock protecting PTAB[vspace_id][x][y]
     266    _spin_lock_acquire( &_ptabs_spin_lock[vspace_id][x][y] );
     267
    357268    // get ptd in PT1
    358     _get_lock(&lock_next_pt2[vspace_id][x][y]);
    359     ptd = _physical_read(pt1_pbase + 4 * ix1);
     269    ptd = _physical_read( pt1_pbase + 4 * ix1 );
    360270
    361271    if ((ptd & PTE_V) == 0)    // undefined PTD: compute PT2 base address,
    362272                               // and set a new PTD in PT1
    363273    {
     274        // get a new pt2_id
    364275        pt2_id = _ptabs_next_pt2[vspace_id][x][y];
     276        _ptabs_next_pt2[vspace_id][x][y] = pt2_id + 1;
     277
     278        // check overflow
    365279        if (pt2_id == _ptabs_max_pt2)
    366280        {
    367             _puts("\n[BOOT ERROR] in boot_add_pte2() : PTAB[");
    368             _putd( vspace_id );
    369             _puts(",");
    370             _putd( x );
    371             _puts(",");
    372             _putd( y );
    373             _puts("] contains not enough PT2s\n");
     281            _printf("\n[BOOT ERROR] in boot_add_pte2() : PTAB[%d,%d,%d]"
     282                    " contains not enough PT2s\n", vspace_id, x, y );
    374283            _exit();
    375284        }
     
    377286        pt2_pbase = pt1_pbase + PT1_SIZE + PT2_SIZE * pt2_id;
    378287        ptd = PTE_V | PTE_T | (unsigned int) (pt2_pbase >> 12);
     288
     289        // set PTD into PT1
    379290        _physical_write( pt1_pbase + 4*ix1, ptd);
    380         _ptabs_next_pt2[vspace_id][x][y] = pt2_id + 1;
    381291    }
    382292    else                       // valid PTD: compute PT2 base address
     
    385295    }
    386296
    387     _release_lock(&lock_next_pt2[vspace_id][x][y]);
    388297    // set PTE in PT2 : flags & PPN in two 32 bits words
    389298    pte2_paddr  = pt2_pbase + 8 * ix2;
    390     _physical_write(pte2_paddr     , (PTE_V |flags) );
    391     _physical_write(pte2_paddr + 4 , ppn);
     299    _physical_write(pte2_paddr     , (PTE_V | flags) );
     300    _physical_write(pte2_paddr + 4 , ppn );
     301
     302    // release lock protecting PTAB[vspace_id][x][y]
     303    _spin_lock_release( &_ptabs_spin_lock[vspace_id][x][y] );
     304
     305    asm volatile ("sync");
    392306
    393307}   // end boot_add_pte2()
     
    397311// defined by alignPow2 == L2(alignement).
    398312////////////////////////////////////////////////////////////////////////////////////
    399 paddr_t paddr_align_to(paddr_t paddr, unsigned int alignPow2)
     313paddr_t paddr_align_to( paddr_t paddr, unsigned int alignPow2 )
    400314{
    401315    paddr_t mask = (1 << alignPow2) - 1;
     
    403317}
    404318
    405 unsigned int vaddr_align_to(unsigned int vaddr, unsigned int alignPow2)
     319unsigned int vaddr_align_to( unsigned int vaddr, unsigned int alignPow2 )
    406320{
    407321    unsigned int mask = (1 << alignPow2) - 1;
     
    412326// This function map a vseg identified by the vseg pointer.
    413327//
    414 // A given vseg can be mapped in Big Physical Pages (BPP: 2 Mbytes) or in a
     328// A given vseg can be mapped in a Big Physical Pages (BPP: 2 Mbytes) or in a
    415329// Small Physical Pages (SPP: 4 Kbytes), depending on the "big" attribute of vseg,
    416330// with the following rules:
     
    424338//    account the alignment constraints and register it in vobj->vbase field.
    425339//
    426 // 2) Second step: it allocates the required number of physical pages,
     340// 2) Second step: it allocates the required number of contiguous physical pages,
    427341//    computes the physical base address (if the vseg is not identity mapping),
    428342//    and register it in the vseg pbase field.
    429 //    Only the 4 vsegs used by the boot code and the peripheral vsegs
    430 //    can be identity mapping: The first big physical page in cluster[0,0]
    431 //    is reserved for the 4 boot vsegs.
     343//    Only the vsegs used by the boot code and the peripheral vsegs
     344//    can be identity mapping. The first big physical page in cluster[0,0]
     345//    is reserved for the boot vsegs.
    432346//
    433 // 3) Third step (only for vseg that have the VOBJ_TYPE_PTAB): all page tables
    434 //    associated to the various vspaces must be packed in the same vseg.
    435 //    We divide the vseg in M sub-segments, and compute the vbase and pbase
    436 //    addresses for each page table, and register it in the _ptabs_paddr
     347// 3) Third step (only for vseg that have the VOBJ_TYPE_PTAB): the M page tables
     348//    associated to the M vspaces must be packed in the same vseg.
     349//    We divide this vseg in M sub-segments, and compute the vbase and pbase
     350//    addresses for M page tables, and register these addresses in the _ptabs_paddr
    437351//    and _ptabs_vaddr arrays.
    438352// 
     
    496410    //////////// - if vseg is ram      :  ppn <= physical memory allocator
    497411
    498     unsigned int ppn;          // first physical page index ( 28 bits = |x|y|bppi|sppi| )
    499     unsigned int vpn;          // first virtual page index  ( 20 bits = |ix1|ix2| )
    500     unsigned int vpn_max;      // last  virtual page index  ( 20 bits = |ix1|ix2| )
     412    unsigned int ppn;          // first physical page index (28 bits = |x|y|bppi|sppi|)
     413    unsigned int vpn;          // first virtual page index  (20 bits = |ix1|ix2|)
     414    unsigned int vpn_max;      // last  virtual page index  (20 bits = |ix1|ix2|)
    501415
    502416    vpn     = vseg->vbase >> 12;
     
    539453                    paddr_t      paddr = _ptabs_paddr[vsid][x_dest][y_dest] + (ix1<<2);
    540454                    unsigned int pte1  = _physical_read( paddr );
    541 #if (BOOT_DEBUG_PT > 1)
    542 _get_lock(&lock_tty);
    543 _puts("[BOOT DEBUG] ");
    544 _puts( vseg->name );
    545 _puts(" in cluster[");
    546 _putd( x_dest );
    547 _puts(",");
    548 _putd( y_dest );
    549 _puts("] : vbase = ");
    550 _putx( vseg->vbase );
    551 _puts(" / paddr = ");
    552 _putl( paddr );
    553 _puts(" / pte1 = ");
    554 _putx( pte1 );
    555 _puts(" by processor ");
    556 _putd(_get_procid());
    557 _puts("\n");
    558 _release_lock(&lock_tty);
    559 #endif
     455
    560456                    if ( (pte1 & PTE_V) == 0 )     // BPP not allocated yet
    561457                    {
     
    572468                        if (pte1 & PTE_W) pte1_mode |= W_MODE_MASK;
    573469                        if (pte1 & PTE_U) pte1_mode |= U_MODE_MASK;
    574                         if (vseg->mode != pte1_mode) {
    575                             _puts("\n[BOOT ERROR] in boot_vseg_map() : vseg ");
    576                             _puts( vseg->name );
    577                             _puts(" has different flags (");
    578                             _putx( vseg->mode );
    579                             _puts(") than other vsegs sharing the same big page (");
    580                             _putx( pte1_mode );
    581                             _puts(")");
     470                        if (vseg->mode != pte1_mode)
     471                        {
     472                            _printf("\n[BOOT ERROR] in boot_vseg_map() : "
     473                                    "vseg %s has different flags than another vseg "
     474                                    "in the same BPP\n", vseg->name );
    582475                            _exit();
    583476                        }
    584 
    585477                        ppn = ((pte1 << 9) & 0x0FFFFE00);
    586478                    }
     
    597489    // update vseg.pbase field and update vsegs chaining
    598490    vseg->pbase     = ((paddr_t)ppn) << 12;
     491    vseg->mapped    = 1;
    599492    vseg->next_vseg = pseg->next_vseg;
    600493    pseg->next_vseg = (unsigned int)vseg;
     
    637530    }
    638531
     532    asm volatile ("sync");
     533
    639534#if BOOT_DEBUG_PT
    640 _get_lock(&lock_tty);
    641 _puts("[BOOT DEBUG] ");
    642 _puts( vseg->name );
    643 _puts(" in cluster[");
    644 _putd( x_dest );
    645 _puts(",");
    646 _putd( y_dest );
    647 _puts("] : vbase = ");
    648 _putx( vseg->vbase );
    649 _puts(" / length = ");
    650 _putx( vseg->length );
    651 if ( big ) _puts(" / BIG   / npages = ");
    652 else       _puts(" / SMALL / npages = ");
    653 _putd( npages );
    654 _puts(" / pbase = ");
    655 _putl( vseg->pbase );
    656 _puts("\n");
    657 _release_lock(&lock_tty);
     535if ( big )
     536_printf("\n[BOOT] vseg %s : cluster[%d,%d] / "
     537       "vbase = %x / length = %x / BIG    / npages = %d / pbase = %l\n",
     538       vseg->name, x_dest, y_dest, vseg->vbase, vseg->length, npages, vseg-> pbase );
     539else
     540_printf("\n[BOOT] vseg %s : cluster[%d,%d] / "
     541        "vbase = %x / length = %x / SMALL / npages = %d / pbase = %l\n",
     542       vseg->name, x_dest, y_dest, vseg->vbase, vseg->length, npages, vseg-> pbase );
    658543#endif
    659544
     
    661546
    662547/////////////////////////////////////////////////////////////////////////////////////
    663 // For the vseg defined by the vseg pointer, this function register all PTEs
     548// For the vseg defined by the vseg pointer, this function register PTEs
    664549// in one or several page tables.
    665550// It is a global vseg (kernel vseg) if (vspace_id == 0xFFFFFFFF).
    666551// The number of involved PTABs depends on the "local" and "global" attributes:
    667552//  - PTEs are replicated in all vspaces for a global vseg.
    668 //  - PTEs are replicated in all clusters for a non local vseg.
     553//  - PTEs are replicated in all clusters containing procs for a non local vseg.
    669554/////////////////////////////////////////////////////////////////////////////////////
    670555void boot_vseg_pte( mapping_vseg_t*  vseg,
     
    690575
    691576    // compute vseg flags
    692     // The three flags (Local, Remote and Dirty) are set to 1 to reduce
    693     // latency of TLB miss (L/R) and write (D): Avoid hardware update
    694     // mechanism for these flags because GIET_VM does use these flags.
     577    // The three flags (Local, Remote and Dirty) are set to 1
     578    // to avoid hardware update for these flags, because GIET_VM
     579    // does use these flags.
    695580    unsigned int flags = 0;
    696581    if (vseg->mode & C_MODE_MASK) flags |= PTE_C;
     
    711596    else            npages  = (vpn_max>>9) - (vpn>>9) + 1;
    712597
    713     // compute destination cluster coordinates
    714     unsigned int        x_dest;
    715     unsigned int        y_dest;
    716     mapping_header_t*   header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
    717     mapping_cluster_t*  cluster = _get_cluster_base(header);
    718     mapping_pseg_t*     pseg    = _get_pseg_base(header);
    719     pseg     = pseg + vseg->psegid;
    720     cluster  = cluster + pseg->clusterid;
    721     x_dest   = cluster->x;
    722     y_dest   = cluster->y;
    723 
    724     unsigned int p;     // iterator for physical page index
    725     unsigned int x;     // iterator for cluster x coordinate 
    726     unsigned int y;     // iterator for cluster y coordinate 
    727     unsigned int v;     // iterator for vspace index
     598    // compute destination cluster coordinates, for local vsegs
     599    mapping_header_t*   header       = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
     600    mapping_cluster_t*  cluster      = _get_cluster_base(header);
     601    mapping_pseg_t*     pseg         = _get_pseg_base(header);
     602    mapping_pseg_t*     pseg_dest    = &pseg[vseg->psegid];
     603    mapping_cluster_t*  cluster_dest = &cluster[pseg_dest->clusterid];
     604    unsigned int        x_dest       = cluster_dest->x;
     605    unsigned int        y_dest       = cluster_dest->y;
     606
     607    unsigned int p;           // iterator for physical page index
     608    unsigned int x;           // iterator for cluster x coordinate 
     609    unsigned int y;           // iterator for cluster y coordinate 
     610    unsigned int v;           // iterator for vspace index
    728611
    729612    // loop on PTEs
     
    757640                for ( y = 0 ; y < Y_SIZE ; y++ )
    758641                {
    759                     if ( big )   // big pages => PTE1s
     642                    if ( cluster[(x * Y_SIZE) + y].procs )
    760643                    {
    761                         boot_add_pte1( vsid,
    762                                        x,
    763                                        y,
    764                                        vpn + (p<<9),
    765                                        flags,
    766                                        ppn + (p<<9) );
    767                     }
    768                     else         // small pages => PTE2s
    769                     {
    770                         boot_add_pte2( vsid,
    771                                        x,
    772                                        y,
    773                                        vpn + p,
    774                                        flags,
    775                                        ppn + p );
     644                        if ( big )   // big pages => PTE1s
     645                        {
     646                            boot_add_pte1( vsid,
     647                                           x,
     648                                           y,
     649                                           vpn + (p<<9),
     650                                           flags,
     651                                           ppn + (p<<9) );
     652                        }
     653                        else         // small pages => PTE2s
     654                        {
     655                            boot_add_pte2( vsid,
     656                                           x,
     657                                           y,
     658                                           vpn + p,
     659                                           flags,
     660                                           ppn + p );
     661                        }
    776662                    }
    777663                }
     
    808694                for ( y = 0 ; y < Y_SIZE ; y++ )
    809695                {
    810                     for ( v = 0 ; v < header->vspaces ; v++ )
     696                    if ( cluster[(x * Y_SIZE) + y].procs )
    811697                    {
    812                         if ( big )  // big pages => PTE1s
     698                        for ( v = 0 ; v < header->vspaces ; v++ )
    813699                        {
    814                             boot_add_pte1( v,
    815                                            x,
    816                                            y,
    817                                            vpn + (p<<9),
    818                                            flags,
    819                                            ppn + (p<<9) );
    820                         }
    821                         else        // small pages -> PTE2s
    822                         {
    823                             boot_add_pte2( v,
    824                                            x,
    825                                            y,
    826                                            vpn + p,
    827                                            flags,
    828                                            ppn + p );
     700                            if ( big )  // big pages => PTE1s
     701                            {
     702                                boot_add_pte1( v,
     703                                               x,
     704                                               y,
     705                                               vpn + (p<<9),
     706                                               flags,
     707                                               ppn + (p<<9) );
     708                            }
     709                            else        // small pages -> PTE2s
     710                            {
     711                                boot_add_pte2( v,
     712                                               x,
     713                                               y,
     714                                               vpn + p,
     715                                               flags,
     716                                               ppn + p );
     717                            }
    829718                        }
    830719                    }
     
    833722        }
    834723    }  // end for pages
     724
     725    asm volatile ("sync");
     726
    835727}  // end boot_vseg_pte()
    836728
     729
    837730///////////////////////////////////////////////////////////////////////////////
    838 // This function initialises the page tables for all vspaces defined
    839 // in the mapping_info data structure.
    840 // For each vspace, there is one page table per cluster.
     731// Processor P[x][y][0] computes physical base address for all globals vsegs,
     732// using the local Page Table, to check page tables initialisation.
     733///////////////////////////////////////////////////////////////////////////////
     734void boot_ptab_check( unsigned int x,
     735                      unsigned int y )
     736{
     737    mapping_header_t*   header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
     738    mapping_vseg_t*     vseg   = _get_vseg_base(header);
     739    page_table_t*       ptab   = (page_table_t*)_ptabs_vaddr[0][x][y];
     740
     741    unsigned int vseg_id;
     742    for (vseg_id = 0; vseg_id < header->globals; vseg_id++)
     743    {
     744        unsigned int  vpn   = vseg[vseg_id].vbase >> 12;
     745        unsigned int  ppn   = 0; 
     746        unsigned int  flags = 0;
     747        _v2p_translate( ptab , vpn , &ppn , &flags );
     748        _printf("@@@ P[%d,%d,0] access vseg %s : vpn = %x / ppn = %x\n",
     749                x , y , vseg[vseg_id].name , vpn , ppn ); 
     750    }
     751}
     752
     753///////////////////////////////////////////////////////////////////////////////
     754// This function is executed by  processor[x][y][0] in each cluster
     755// containing at least one processor.
     756// It initialises all page table for all global or private vsegs
     757// mapped in cluster[x][y], as specified in the mapping.
    841758// In each cluster all page tables for the different vspaces must be
    842759// packed in one vseg occupying one single BPP (Big Physical Page).
    843760//
    844 // This fonction is executed by the processor[x][y][0], the vsegs mapped in the
    845 // cluster[x][y] in map.bin file are handled by the processor[x][y][0]
    846 //
    847761// For each vseg, the mapping is done in two steps:
    848762// 1) mapping : the boot_vseg_map() function allocates contiguous BPPs
    849763//    or SPPs (if the vseg is not associated to a peripheral), and register
    850764//    the physical base address in the vseg pbase field. It initialises the
    851 //    _ptabs_vaddr and _ptabs_paddr arrays if the vseg is a PTAB.
     765//    _ptabs_vaddr[] and _ptabs_paddr[] arrays if the vseg is a PTAB.
    852766//
    853767// 2) page table initialisation : the boot_vseg_pte() function initialise
     
    857771//
    858772// We must handle vsegs in the following order
    859 //   1) all global vsegs containing a page table,
    860 //   2) all global vsegs occupying more than one BPP,
    861 //   3) all others global vsegs
    862 //   4) all private vsegs in user space.
     773//   1) global vseg containing PTAB mapped in cluster[x][y],
     774//   2) global vsegs occupying more than one BPP mapped in cluster[x][y],
     775//   3) others global vsegs mapped in cluster[x][y],
     776//   4) all private vsegs in all user spaces mapped in cluster[x][y].
    863777///////////////////////////////////////////////////////////////////////////////
    864 void boot_ptabs_init()
     778void boot_ptab_init( unsigned int cx,
     779                     unsigned int cy )
    865780{
    866781    mapping_header_t*   header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
     
    875790
    876791    unsigned int procid     = _get_procid();
    877     unsigned int x_cluster  = (procid >> (Y_WIDTH + P_WIDTH)) & ((1<<X_WIDTH)-1);
    878     unsigned int y_cluster  = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
    879792    unsigned int lpid       = procid & ((1<<P_WIDTH)-1);
    880793
    881     if(lpid)
    882     {
    883         _puts("[BOOT ERROR] boot_ptabs_init() : error local processor id\n");
     794    if( lpid )
     795    {
     796        _printf("\n[BOOT ERROR] in boot_ptab_init() : "
     797                "P[%d][%d][%d] should not execute it\n", cx, cy, lpid );
    884798        _exit();
    885799    }
    886800
    887     if (header->vspaces == 0 )
    888     {
    889         _puts("\n[BOOT ERROR] in boot_ptabs_init() : mapping ");
    890         _puts( header->name );
    891         _puts(" contains no vspace\n");
     801    if ( header->vspaces == 0 )
     802    {
     803        _printf("\n[BOOT ERROR] in boot_ptab_init() : "
     804                "mapping %s contains no vspace\n", header->name );
    892805        _exit();
    893806    }
    894807
    895     ///////// Phase 1 : global vsegs containing a PTAB (two loops required)
    896 
    897 #if BOOT_DEBUG_PT
    898 _get_lock(&lock_tty);
    899 _puts("\n[BOOT DEBUG] map PTAB global vsegs in cluster[");
    900 _putd(x_cluster);
    901 _puts(",");
    902 _putd(y_cluster);
    903 _puts("]");
    904 _puts("\n");
    905 _release_lock(&lock_tty);
    906 #endif
    907 
     808    ///////// Phase 1 : global vseg containing the PTAB (two barriers required)
     809
     810    // get local PTAB vseg
     811    unsigned int found = 0;
    908812    for (vseg_id = 0; vseg_id < header->globals; vseg_id++)
    909813    {
     
    912816        cluster = _get_cluster_base(header) + pseg->clusterid;
    913817        if ( (vobj[vobj_id].type == VOBJ_TYPE_PTAB) &&
    914              (cluster->x == x_cluster) &&
    915              (cluster->y == y_cluster))
    916         {
    917             boot_vseg_map( &vseg[vseg_id], 0xFFFFFFFF );
    918             vseg[vseg_id].mapped = 1;
    919         }
    920     }
    921 
    922     _barrier_wait(&barrier_boot);
    923 
    924     for (vseg_id = 0; vseg_id < header->globals; vseg_id++)
    925     {
    926         unsigned int vobj_id = vseg[vseg_id].vobj_offset;
    927         pseg    = _get_pseg_base(header) + vseg[vseg_id].psegid;
    928         cluster = _get_cluster_base(header) + pseg->clusterid;
    929         if ( (vobj[vobj_id].type == VOBJ_TYPE_PTAB) &&
    930              (cluster->x == x_cluster) &&
    931              (cluster->y == y_cluster))
    932         {
    933             boot_vseg_pte( &vseg[vseg_id], 0xFFFFFFFF );
    934             vseg[vseg_id].mapped = 1;
    935         }
    936     }
    937 
    938     _barrier_wait(&barrier_boot);
    939 
    940     ///////// Phase 2 : global vsegs occupying more than one BPP (one loop)
    941 
    942 #if BOOT_DEBUG_PT
    943 _get_lock(&lock_tty);
    944 _puts("\n[BOOT DEBUG] map all multi-BPP global vseg in cluster[");
    945 _putd(x_cluster);
    946 _puts(",");
    947 _putd(y_cluster);
    948 _puts("]");
    949 _puts("\n");
    950 _release_lock(&lock_tty);
    951 #endif   
     818             (cluster->x == cx) && (cluster->y == cy) )
     819        {
     820            found = 1;
     821            break;
     822        }
     823    }
     824    if ( found == 0 )
     825    {
     826        _printf("\n[BOOT ERROR] in boot_ptab_init() : "
     827                "cluster[%d][%d] contains no PTAB vseg\n", cx , cy );
     828        _exit();
     829    }
     830
     831    boot_vseg_map( &vseg[vseg_id], 0xFFFFFFFF );
     832
     833    //////////////////////////////////////////////
     834    _simple_barrier_wait( &_barrier_all_clusters );
     835    //////////////////////////////////////////////
     836
     837    boot_vseg_pte( &vseg[vseg_id], 0xFFFFFFFF );
     838
     839    //////////////////////////////////////////////
     840    _simple_barrier_wait( &_barrier_all_clusters );
     841    //////////////////////////////////////////////
     842
     843    ///////// Phase 2 : global vsegs occupying more than one BPP
    952844
    953845    for (vseg_id = 0; vseg_id < header->globals; vseg_id++)
     
    958850        if ( (vobj[vobj_id].length > 0x200000) &&
    959851             (vseg[vseg_id].mapped == 0) &&
    960              (cluster->x == x_cluster) &&
    961              (cluster->y == y_cluster))
     852             (cluster->x == cx) && (cluster->y == cy) )
    962853        {
    963854            boot_vseg_map( &vseg[vseg_id], 0xFFFFFFFF );
    964             vseg[vseg_id].mapped = 1;
    965855            boot_vseg_pte( &vseg[vseg_id], 0xFFFFFFFF );
    966856        }
    967857    }
    968858
    969     ///////// Phase 3 : all others global vsegs (one loop)
    970 
    971 #if BOOT_DEBUG_PT
    972 _get_lock(&lock_tty);
    973 _puts("\n[BOOT DEBUG] map all others global in cluster[ ");
    974 _putd(x_cluster);
    975 _puts(",");
    976 _putd(y_cluster);
    977 _puts("]");
    978 _puts("\n");
    979 _release_lock(&lock_tty);
    980 #endif
     859    ///////// Phase 3 : all others global vsegs
    981860
    982861    for (vseg_id = 0; vseg_id < header->globals; vseg_id++)
    983     {
    984         unsigned int vobj_id = vseg[vseg_id].vobj_offset;
     862    {
    985863        pseg    = _get_pseg_base(header) + vseg[vseg_id].psegid;
    986864        cluster = _get_cluster_base(header) + pseg->clusterid;
    987         if ( (vobj[vobj_id].length <= 0x200000) &&
    988              (vseg[vseg_id].mapped == 0) &&
    989              (cluster->x == x_cluster) &&
    990              (cluster->y == y_cluster))
     865        if ( (vseg[vseg_id].mapped == 0) &&
     866             (cluster->x == cx) && (cluster->y == cy) )
    991867        {
    992868            boot_vseg_map( &vseg[vseg_id], 0xFFFFFFFF );
    993             vseg[vseg_id].mapped = 1;
    994869            boot_vseg_pte( &vseg[vseg_id], 0xFFFFFFFF );
    995870        }
    996871    }
    997872
    998     ///////// Phase 4 : all private vsegs (two nested loops)
     873    ///////// Phase 4 : all private vsegs
    999874
    1000875    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++)
    1001876    {
    1002 
    1003 #if BOOT_DEBUG_PT
    1004 _get_lock(&lock_tty);
    1005 _puts("\n[BOOT DEBUG] map private vsegs for vspace ");
    1006 _puts( vspace[vspace_id].name );
    1007 _puts(" in cluster[ ");
    1008 _putd(x_cluster);
    1009 _puts(",");
    1010 _putd(y_cluster);
    1011 _puts("]");
    1012 _puts("\n");
    1013 _release_lock(&lock_tty);
    1014 #endif
    1015 
    1016877        for (vseg_id = vspace[vspace_id].vseg_offset;
    1017878             vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs);
     
    1020881            pseg    = _get_pseg_base(header) + vseg[vseg_id].psegid;
    1021882            cluster = _get_cluster_base(header) + pseg->clusterid;
    1022             if((vseg[vseg_id].mapped == 0) &&
    1023                (cluster->x == x_cluster) &&
    1024                (cluster->y == y_cluster))
     883            if ( (cluster->x == cx) && (cluster->y == cy) )
    1025884            {
    1026885                boot_vseg_map( &vseg[vseg_id], vspace_id );
    1027                 vseg[vseg_id].mapped = 1;
    1028886                boot_vseg_pte( &vseg[vseg_id], vspace_id );
    1029887            }
     
    1031889    }
    1032890
    1033 #if (BOOT_DEBUG_PT > 2)
    1034 _get_lock(&lock_tty);
    1035 mapping_vseg_t*    curr;
    1036 mapping_pseg_t*    pseg    = _get_pseg_base(header);
    1037 mapping_cluster_t* cluster = _get_cluster_base(header);
    1038 unsigned int       pseg_id;
    1039 for( pseg_id = 0 ; pseg_id < header->psegs ; pseg_id++ )
     891    //////////////////////////////////////////////
     892    _simple_barrier_wait( &_barrier_all_clusters );
     893    //////////////////////////////////////////////
     894
     895} // end boot_ptab_init()
     896
     897////////////////////////////////////////////////////////////////////////////////
     898// This function should be executed by P[0][0][0] only. It complete the
     899// page table initialisation, taking care of all global vsegs that are
     900// not mapped in a cluster containing a processor, and have not been
     901// handled by the boot_ptab_init(x,y) function.
     902// An example of such vsegs are the external peripherals in TSAR_LETI platform.
     903////////////////////////////////////////////////////////////////////////////////
     904void boot_ptab_extend()
    1040905{
    1041     unsigned int cluster_id = pseg[pseg_id].clusterid;
    1042     _puts("\n[BOOT DEBUG] vsegs mapped on pseg ");
    1043     _puts( pseg[pseg_id].name );
    1044     _puts(" in cluster[");
    1045     _putd( cluster[cluster_id].x );
    1046     _puts(",");
    1047     _putd( cluster[cluster_id].y );
    1048     _puts("]\n");
    1049     for( curr = (mapping_vseg_t*)pseg[pseg_id].next_vseg ;
    1050          curr != 0 ;
    1051          curr = (mapping_vseg_t*)curr->next_vseg )
    1052     {
    1053         _puts(" - vseg ");
    1054         _puts( curr->name );
    1055         _puts(" : len = ");
    1056         _putx( curr->length );
    1057         _puts(" / vbase ");
    1058         _putx( curr->vbase );
    1059         _puts(" / pbase ");
    1060         _putl( curr->pbase );
    1061         _puts("\n");
    1062     } 
    1063 }
    1064 _release_lock(&lock_tty);
    1065 #endif
    1066 
    1067 } // end boot_ptabs_init()
    1068 
    1069 ///////////////////////////////////////////////////////////////////////////////
    1070 // This function initializes the private vobjs that have the CONST type.
    1071 // The MMU is supposed to be activated...
    1072 ///////////////////////////////////////////////////////////////////////////////
    1073 void boot_vobjs_init()
    1074 {
    1075     mapping_header_t* header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
    1076     mapping_vspace_t* vspace = _get_vspace_base(header);
    1077     mapping_vobj_t* vobj     = _get_vobj_base(header);
    1078 
    1079     unsigned int vspace_id;
    1080     unsigned int vobj_id;
    1081 
    1082     // loop on the vspaces
    1083     for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++)
    1084     {
    1085 
    1086 #if BOOT_DEBUG_VOBJS
    1087 _puts("\n[BOOT DEBUG] ****** vobjs initialisation in vspace ");
    1088 _puts(vspace[vspace_id].name);
    1089 _puts(" ******\n");
    1090 #endif
    1091 
    1092         _set_mmu_ptpr( (unsigned int)(_ptabs_paddr[vspace_id][0][0] >> 13) );
    1093 
    1094         // loop on the vobjs
    1095         for (vobj_id = vspace[vspace_id].vobj_offset;
    1096              vobj_id < (vspace[vspace_id].vobj_offset + vspace[vspace_id].vobjs);
    1097              vobj_id++)
    1098         {
    1099             if ( (vobj[vobj_id].type) == VOBJ_TYPE_CONST )
    1100             {
    1101 #if BOOT_DEBUG_VOBJS
    1102 _puts("CONST   : ");
    1103 _puts(vobj[vobj_id].name);
    1104 _puts(" / vaddr  = ");
    1105 _putx(vobj[vobj_id].vaddr);
    1106 _puts(" / paddr  = ");
    1107 _putl(vobj[vobj_id].paddr);
    1108 _puts(" / value  = ");
    1109 _putx(vobj[vobj_id].init);
    1110 _puts("\n");
    1111 #endif
    1112                 unsigned int* addr = (unsigned int *) vobj[vobj_id].vbase;
    1113                 *addr = vobj[vobj_id].init;
    1114             }
    1115         }
    1116     }
    1117 } // end boot_vobjs_init()
     906
     907    mapping_header_t*   header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
     908    mapping_vseg_t*     vseg   = _get_vseg_base(header);
     909
     910    unsigned int vseg_id;
     911
     912    for (vseg_id = 0; vseg_id < header->globals; vseg_id++)
     913    {
     914        if ( vseg[vseg_id].mapped == 0 ) 
     915        {
     916            boot_vseg_map( &vseg[vseg_id], 0xFFFFFFFF );
     917            boot_vseg_pte( &vseg[vseg_id], 0xFFFFFFFF );
     918        }
     919    }
     920}  // end boot_ptab_extend()
    1118921
    1119922///////////////////////////////////////////////////////////////////////////////
     
    1147950    {
    1148951        mapping_cluster_t* cluster = _get_cluster_base(header);
    1149         _puts("\n[BOOT ERROR] No vobj of type SCHED in cluster [");
    1150         _putd( cluster[cluster_id].x );
    1151         _puts(",");
    1152         _putd( cluster[cluster_id].y );
    1153         _puts("]\n");
     952        _printf("\n[BOOT ERROR] No vobj of type SCHED in cluster [%d,%d]\n",
     953                cluster[cluster_id].x, cluster[cluster_id].y );
    1154954        _exit();
    1155955    }
     
    1157957
    1158958////////////////////////////////////////////////////////////////////////////////////
    1159 // This function initialises all processors schedulers.
    1160 // This is done by processor 0, and the MMU must be activated.
    1161 // - In Step 1, it initialises the _schedulers[x][y][l] pointers array, and scan
    1162 //              the processors for a first initialisation of the schedulers:
    1163 //              idle_task context, and HWI / SWI / PTI vectors.
     959// This function is executed in parallel by all processors P[x][y][0].
     960// It initialises all schedulers in cluster [x][y]. The MMU must be activated.
     961// It is split in two phases separated by a synchronisation barrier.
     962// - In Step 1, it initialises the _schedulers[x][y][l] pointers array,
     963//              the idle_task context and the HWI / PTI vectors.
    1164964// - In Step 2, it scan all tasks in all vspaces to complete the tasks contexts,
    1165 //              initialisation as specified in the mapping_info data structure.
     965//              initialisation as specified in the mapping_info data structure,
     966//              and set the CP0_SCHED register.
    1166967////////////////////////////////////////////////////////////////////////////////////
    1167 void boot_schedulers_init()
     968void boot_scheduler_init( unsigned int x,
     969                          unsigned int y )
    1168970{
    1169     mapping_header_t*  header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
    1170     mapping_cluster_t* cluster = _get_cluster_base(header);
    1171     mapping_vspace_t*  vspace  = _get_vspace_base(header);
    1172     mapping_task_t*    task    = _get_task_base(header);
    1173     mapping_vobj_t*    vobj    = _get_vobj_base(header);
    1174     mapping_periph_t*  periph  = _get_periph_base(header);
    1175     mapping_irq_t*     irq     = _get_irq_base(header);
    1176 
    1177     unsigned int cluster_id;    // cluster index in mapping_info
    1178     unsigned int periph_id;     // peripheral index in mapping_info
    1179     unsigned int irq_id;        // irq index in mapping_info
    1180     unsigned int vspace_id;     // vspace index in mapping_info
    1181     unsigned int task_id;       // task index in mapping_info
    1182     unsigned int vobj_id;       // vobj index in mapping_info
    1183 
    1184     unsigned int lpid;          // local processor index (for several loops)
    1185 
    1186     // WTI allocators to processors (for HWIs translated to WTIs) 
    1187     // In all clusters the first NB_PROCS_MAX WTIs are reserved for WAKUP
    1188     unsigned int alloc_wti_channel[X_SIZE*Y_SIZE];   // one per cluster
    1189 
    1190     // pointers on the XCU and PIC peripherals
     971    mapping_header_t*    header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
     972    mapping_cluster_t*   cluster = _get_cluster_base(header);
     973    mapping_vspace_t*    vspace  = _get_vspace_base(header);
     974    mapping_task_t*      task    = _get_task_base(header);
     975    mapping_vobj_t*      vobj    = _get_vobj_base(header);
     976    mapping_periph_t*    periph  = _get_periph_base(header);
     977    mapping_irq_t*       irq     = _get_irq_base(header);
     978
     979    unsigned int         periph_id;
     980    unsigned int         irq_id;
     981    unsigned int         vspace_id;
     982    unsigned int         task_id;
     983    unsigned int         vobj_id;
     984
     985    unsigned int         sched_vbase;          // schedulers array vbase address
     986    unsigned int         sched_length;         // schedulers array length
     987    static_scheduler_t*  psched;               // pointer on processor scheduler
     988
     989    unsigned int cluster_id = x * Y_SIZE + y; 
     990    unsigned int nprocs = cluster[cluster_id].procs;
     991    unsigned int lpid;                       
     992   
     993    /////////////////////////////////////////////////////////////////////////
     994    // Step 1 : initialize the schedulers[] array of pointers,
     995    //          the idle task context and the HWI and PTI interrupt vectors.
     996    //          The WTI interrupt vector entries corresponding to interrupts
     997    //          generated by the PIC component are handled later.
     998
     999    // get scheduler array virtual base address in cluster[x,y]
     1000    boot_get_sched_vaddr( cluster_id, &sched_vbase, &sched_length );
     1001
     1002    if ( sched_length < (nprocs<<13) ) // 8 Kbytes per scheduler
     1003    {
     1004        _printf("\n[BOOT ERROR] Sched segment too small in cluster[%d,%d]\n", x, y );
     1005        _exit();
     1006    }
     1007
     1008    // loop on local processors
     1009    for ( lpid = 0 ; lpid < nprocs ; lpid++ )
     1010    {
     1011        // get scheduler pointer and initialise the schedulers pointers array
     1012        psched = (static_scheduler_t*)(sched_vbase + (lpid<<13));
     1013        _schedulers[x][y][lpid] = psched;
     1014
     1015        // initialise the "tasks" and "current" variables default values
     1016        psched->tasks   = 0;
     1017        psched->current = IDLE_TASK_INDEX;
     1018
     1019        // default values for HWI / PTI / SWI vectors (valid bit = 0)
     1020        unsigned int slot;
     1021        for (slot = 0; slot < 32; slot++)
     1022        {
     1023            psched->hwi_vector[slot] = 0;
     1024            psched->pti_vector[slot] = 0;
     1025            psched->wti_vector[slot] = 0;
     1026        }
     1027
     1028        // WTI[lpid] <= ISR_WAKUP / PTI[lpid] <= ISR_TICK
     1029        psched->wti_vector[lpid] = ISR_WAKUP | 0x80000000;
     1030        psched->pti_vector[lpid] = ISR_TICK  | 0x80000000;
     1031
     1032        // initializes the idle_task context:
     1033        // - the SR slot is 0xFF03 because this task run in kernel mode.
     1034        // - it uses the page table of vspace[0]
     1035        // - it uses the kernel TTY terminal
     1036        // - slots containing addresses (SP,RA,EPC) are initialised by kernel_init()
     1037
     1038        psched->context[IDLE_TASK_INDEX][CTX_CR_ID]   = 0;
     1039        psched->context[IDLE_TASK_INDEX][CTX_SR_ID]   = 0xFF03;
     1040        psched->context[IDLE_TASK_INDEX][CTX_PTPR_ID] = _ptabs_paddr[0][x][y]>>13;
     1041        psched->context[IDLE_TASK_INDEX][CTX_PTAB_ID] = _ptabs_vaddr[0][x][y];
     1042        psched->context[IDLE_TASK_INDEX][CTX_TTY_ID]  = 0;
     1043        psched->context[IDLE_TASK_INDEX][CTX_LTID_ID] = IDLE_TASK_INDEX;
     1044        psched->context[IDLE_TASK_INDEX][CTX_VSID_ID] = 0;
     1045        psched->context[IDLE_TASK_INDEX][CTX_RUN_ID]  = 1;
     1046    }
     1047
     1048    // scan local peripherals to get local XCU
    11911049    mapping_periph_t*  xcu = NULL;
    1192     mapping_periph_t*  pic = NULL;
    1193 
    1194     unsigned int          sched_vbase;  // schedulers array vbase address in a cluster
    1195     unsigned int          sched_length; // schedulers array length
    1196     static_scheduler_t*   psched;       // pointer on processor scheduler
    1197 
    1198     /////////////////////////////////////////////////////////////////////////
    1199     // Step 1 : loop on the clusters and on the processors
    1200     //          to initialize the schedulers[] array of pointers,
    1201     //          idle task context and interrupt vectors.
    1202     // Implementation note:
    1203     // We need to use both (proc_id) to scan the mapping info structure,
    1204     // and (x,y,lpid) to access the schedulers array.
    1205 
    1206     for (cluster_id = 0 ; cluster_id < X_SIZE*Y_SIZE ; cluster_id++)
    1207     {
    1208         unsigned int x          = cluster[cluster_id].x;
    1209         unsigned int y          = cluster[cluster_id].y;
    1210 
    1211 #if BOOT_DEBUG_SCHED
    1212 _puts("\n[BOOT DEBUG] Initialise schedulers in cluster[");
    1213 _putd( x );
    1214 _puts(",");
    1215 _putd( y );
    1216 _puts("]\n");
    1217 #endif
    1218         alloc_wti_channel[cluster_id] = NB_PROCS_MAX;
    1219 
    1220         // checking processors number
    1221         if ( cluster[cluster_id].procs > NB_PROCS_MAX )
    1222         {
    1223             _puts("\n[BOOT ERROR] Too much processors in cluster[");
    1224             _putd( x );
    1225             _puts(",");
    1226             _putd( y );
    1227             _puts("]\n");
    1228             _exit();
    1229         }
    1230  
    1231         // no schedulers initialisation if nprocs == 0
    1232         if ( cluster[cluster_id].procs > 0 )
    1233         {
    1234             // get scheduler array virtual base address in cluster[cluster_id]
    1235             boot_get_sched_vaddr( cluster_id, &sched_vbase, &sched_length );
    1236 
    1237             if ( sched_length < (cluster[cluster_id].procs<<13) ) // 8 Kbytes per scheduler
     1050
     1051    for ( periph_id = cluster[cluster_id].periph_offset ;
     1052          periph_id < cluster[cluster_id].periph_offset + cluster[cluster_id].periphs;
     1053          periph_id++ )
     1054    {
     1055        if( periph[periph_id].type == PERIPH_TYPE_XCU )
     1056        {
     1057            xcu = &periph[periph_id];
     1058
     1059            if ( xcu->arg < (nprocs * header->irq_per_proc) )
    12381060            {
    1239                 _puts("\n[BOOT ERROR] Schedulers segment too small in cluster[");
    1240                 _putd( x );
    1241                 _puts(",");
    1242                 _putd( y );
    1243                 _puts("]\n");
     1061                _printf("\n[BOOT ERROR] Not enough inputs for XCU[%d,%d]\n", x, y );
    12441062                _exit();
    12451063            }
    1246 
    1247             // scan peripherals to find the XCU and the PIC component
    1248 
    1249             xcu = NULL; 
    1250             for ( periph_id = cluster[cluster_id].periph_offset ;
    1251                   periph_id < cluster[cluster_id].periph_offset + cluster[cluster_id].periphs;
    1252                   periph_id++ )
    1253             {
    1254                 if( periph[periph_id].type == PERIPH_TYPE_XCU )
    1255                 {
    1256                     xcu = &periph[periph_id];
    1257 
    1258                     if ( xcu->arg < cluster[cluster_id].procs )
    1259                     {
    1260                         _puts("\n[BOOT ERROR] Not enough inputs for XCU[");
    1261                         _putd( x );
    1262                         _puts(",");
    1263                         _putd( y );
    1264                         _puts("]\n");
    1265                         _exit();
    1266                     }
    1267                 }
    1268                 if( periph[periph_id].type == PERIPH_TYPE_PIC )   
    1269                 {
    1270                     pic = &periph[periph_id];
    1271                 }
    1272             }
    1273             if ( xcu == NULL )
    1274             {         
    1275                 _puts("\n[BOOT ERROR] No XCU component in cluster[");
    1276                 _putd( x );
    1277                 _puts(",");
    1278                 _putd( y );
    1279                 _puts("]\n");
    1280                 _exit();
    1281             }
    1282 
    1283             // loop on processors for schedulers default values
    1284             // initialisation, including WTI and PTI vectors
    1285             for ( lpid = 0 ; lpid < cluster[cluster_id].procs ; lpid++ )
    1286             {
    1287                 // pointer on processor scheduler
    1288                 psched = (static_scheduler_t*)(sched_vbase + (lpid<<13));
    1289 
    1290                 // initialise the schedulers pointers array
    1291                 _schedulers[x][y][lpid] = psched;
    1292 
    1293 #if BOOT_DEBUG_SCHED
    1294 unsigned int   sched_vbase = (unsigned int)_schedulers[x][y][lpid];
    1295 unsigned int   sched_ppn;
    1296 unsigned int   sched_flags;
    1297 paddr_t        sched_pbase;
    1298 
    1299 page_table_t* ptab = (page_table_t*)(_ptabs_vaddr[0][x][y]);
    1300 _v2p_translate( ptab, sched_vbase>>12, &sched_ppn, &sched_flags );
    1301 sched_pbase = ((paddr_t)sched_ppn)<<12;
    1302 
    1303 _puts("\nProc[");
    1304 _putd( x );
    1305 _puts(",");
    1306 _putd( y );
    1307 _puts(",");
    1308 _putd( lpid );
    1309 _puts("] : scheduler vbase = ");
    1310 _putx( sched_vbase );
    1311 _puts(" : scheduler pbase = ");
    1312 _putl( sched_pbase );
    1313 _puts("\n");
    1314 #endif
    1315                 // initialise the "tasks" and "current" variables default values
    1316                 psched->tasks   = 0;
    1317                 psched->current = IDLE_TASK_INDEX;
    1318 
    1319                 // default values for HWI / PTI / SWI vectors (valid bit = 0)
    1320                 unsigned int slot;
    1321                 for (slot = 0; slot < 32; slot++)
    1322                 {
    1323                     psched->hwi_vector[slot] = 0;
    1324                     psched->pti_vector[slot] = 0;
    1325                     psched->wti_vector[slot] = 0;
    1326                 }
    1327 
    1328                 // WTI[lpid] <= ISR_WAKUP / PTI[lpid] <= ISR_TICK
    1329                 psched->wti_vector[lpid] = ISR_WAKUP | 0x80000000;
    1330                 psched->pti_vector[lpid] = ISR_TICK  | 0x80000000;
    1331 
    1332                 // initializes the idle_task context in scheduler:
    1333                 // - the SR slot is 0xFF03 because this task run in kernel mode.
    1334                 // - it uses the page table of vspace[0]
    1335                 // - it uses the kernel TTY terminal
    1336                 // - slots containing addresses (SP, RA, EPC)
    1337                 //   must be initialised by kernel_init()
    1338 
    1339                 psched->context[IDLE_TASK_INDEX][CTX_CR_ID]   = 0;
    1340                 psched->context[IDLE_TASK_INDEX][CTX_SR_ID]   = 0xFF03;
    1341                 psched->context[IDLE_TASK_INDEX][CTX_PTPR_ID] = _ptabs_paddr[0][x][y]>>13;
    1342                 psched->context[IDLE_TASK_INDEX][CTX_PTAB_ID] = _ptabs_vaddr[0][x][y];
    1343                 psched->context[IDLE_TASK_INDEX][CTX_TTY_ID]  = 0;
    1344                 psched->context[IDLE_TASK_INDEX][CTX_LTID_ID] = IDLE_TASK_INDEX;
    1345                 psched->context[IDLE_TASK_INDEX][CTX_VSID_ID] = 0;
    1346                 psched->context[IDLE_TASK_INDEX][CTX_RUN_ID]  = 1;
    1347 
    1348             }  // end for processors
    1349 
    1350             // scan HWIs connected to local XCU
    1351             // for round-robin allocation to processors
    1352             lpid = 0;
    1353             for ( irq_id = xcu->irq_offset ;
    1354                   irq_id < xcu->irq_offset + xcu->irqs ;
    1355                   irq_id++ )
    1356             {
    1357                 unsigned int type    = irq[irq_id].srctype;
    1358                 unsigned int srcid   = irq[irq_id].srcid;
    1359                 unsigned int isr     = irq[irq_id].isr & 0xFFFF;
    1360                 unsigned int channel = irq[irq_id].channel << 16;
    1361 
    1362                 if ( (type != IRQ_TYPE_HWI) || (srcid > 31) )
    1363                 {
    1364                     _puts("\n[BOOT ERROR] Bad IRQ in XCU of cluster[");
    1365                     _putd( x );
    1366                     _puts(",");
    1367                     _putd( y );
    1368                     _puts("]\n");
    1369                     _exit();
    1370                 }
    1371 
    1372                 _schedulers[x][y][lpid]->hwi_vector[srcid] = isr | channel | 0x80000000;
    1373                 lpid = (lpid + 1) % cluster[cluster_id].procs;
    1374 
    1375             } // end for irqs
    1376         } // end if nprocs > 0
    1377     } // end for clusters
    1378 
    1379     // If there is an external PIC component, we scan HWIs connected to PIC
    1380     // for Round Robin allocation (as WTI) to processors.
    1381     // We allocate one WTI per processor, starting from proc[0,0,0],
    1382     // and we increment (cluster_id, lpid) as required.
    1383     if ( pic != NULL )
    1384     {   
    1385         unsigned int cluster_id = 0;   // index in clusters array
    1386         unsigned int lpid       = 0;   // processor local index
    1387 
    1388         // scan IRQS defined in PIC
    1389         for ( irq_id = pic->irq_offset ;
    1390               irq_id < pic->irq_offset + pic->irqs ;
    1391               irq_id++ )
    1392         {
    1393             // compute next values for (cluster_id,lpid)
    1394             // if no more procesor available in current cluster
    1395             unsigned int overflow = 0;
    1396             while ( (lpid >= cluster[cluster_id].procs) ||
    1397                     (alloc_wti_channel[cluster_id] >= xcu->arg) )
    1398             {
    1399                 overflow++;
    1400                 cluster_id = (cluster_id + 1) % (X_SIZE*Y_SIZE);
    1401                 lpid       = 0;
    1402 
    1403                 // overflow detection
    1404                 if ( overflow > (X_SIZE*Y_SIZE*NB_PROCS_MAX*32) )
    1405                 {
    1406                     _puts("\n[BOOT ERROR] Not enough processors for external IRQs\n");
    1407                     _exit();
    1408                 }
    1409             } // end while
    1410 
    1411             unsigned int type    = irq[irq_id].srctype;
    1412             unsigned int srcid   = irq[irq_id].srcid;
    1413             unsigned int isr     = irq[irq_id].isr & 0xFFFF;
    1414             unsigned int channel = irq[irq_id].channel << 16;
    1415 
    1416             if ( (type != IRQ_TYPE_HWI) || (srcid > 31) )
    1417             {
    1418                 _puts("\n[BOOT ERROR] Bad IRQ in PIC component\n");
    1419                 _exit();
    1420             }
    1421 
    1422             // get scheduler[cluster_id] address
    1423             unsigned int x          = cluster[cluster_id].x;
    1424             unsigned int y          = cluster[cluster_id].y;
    1425             unsigned int cluster_xy = (x<<Y_WIDTH) + y;
    1426             psched                  = _schedulers[x][y][lpid];
    1427 
    1428             // update WTI vector for scheduler[cluster_id][lpid]
    1429             unsigned int index            = alloc_wti_channel[cluster_id];
    1430             psched->wti_vector[index]     = isr | channel | 0x80000000;
    1431 
    1432             // increment pointers
    1433             alloc_wti_channel[cluster_id] = index + 1;
    1434             lpid                          = lpid + 1;
    1435 
    1436             // update IRQ fields in mapping for PIC initialisation
    1437             irq[irq_id].dest_id = index;
    1438             irq[irq_id].dest_xy = cluster_xy;
    1439 
    1440         }  // end for IRQs
    1441     } // end if PIC
    1442                
    1443 #if BOOT_DEBUG_SCHED
    1444 for ( cluster_id = 0 ; cluster_id < (X_SIZE*Y_SIZE) ; cluster_id++ )
    1445 {
    1446     unsigned int x          = cluster[cluster_id].x;
    1447     unsigned int y          = cluster[cluster_id].y;
    1448     unsigned int slot;
    1449     unsigned int entry;
    1450     for ( lpid = 0 ; lpid < cluster[cluster_id].procs ; lpid++ )
    1451     {
    1452         psched = _schedulers[x][y][lpid];
    1453        
    1454         _puts("\n*** IRQS for proc[");
    1455         _putd( x );
    1456         _puts(",");
    1457         _putd( y );
    1458         _puts(",");
    1459         _putd( lpid );
    1460         _puts("]\n");
    1461         for ( slot = 0 ; slot < 32 ; slot++ )
    1462         {
    1463             entry = psched->hwi_vector[slot];
    1464             if ( entry & 0x80000000 )
    1465             {
    1466                 _puts(" - HWI ");
    1467                 _putd( slot );
    1468                 _puts(" / isrtype = ");
    1469                 _putd( entry & 0xFFFF );
    1470                 _puts(" / channel = ");
    1471                 _putd( (entry >> 16) & 0x7FFF );
    1472                 _puts("\n");
    1473             }
    1474         }
    1475         for ( slot = 0 ; slot < 32 ; slot++ )
    1476         {
    1477             entry = psched->wti_vector[slot];
    1478             if ( entry & 0x80000000 )
    1479             {
    1480                 _puts(" - WTI ");
    1481                 _putd( slot );
    1482                 _puts(" / isrtype = ");
    1483                 _putd( entry & 0xFFFF );
    1484                 _puts(" / channel = ");
    1485                 _putd( (entry >> 16) & 0x7FFF );
    1486                 _puts("\n");
    1487             }
    1488         }
    1489         for ( slot = 0 ; slot < 32 ; slot++ )
    1490         {
    1491             entry = psched->pti_vector[slot];
    1492             if ( entry & 0x80000000 )
    1493             {
    1494                 _puts(" - PTI ");
    1495                 _putd( slot );
    1496                 _puts(" / isrtype = ");
    1497                 _putd( entry & 0xFFFF );
    1498                 _puts(" / channel = ");
    1499                 _putd( (entry >> 16) & 0x7FFF );
    1500                 _puts("\n");
    1501             }
    1502         }
    1503     }
    1504 }
    1505 #endif
    1506 
    1507     ///////////////////////////////////////////////////////////////////
    1508     // Step 2 : loop on the vspaces and the tasks  to complete
    1509     //          the schedulers and task contexts initialisation.
     1064        }
     1065    }
     1066
     1067    if ( xcu == NULL )
     1068    {         
     1069        _printf("\n[BOOT ERROR] missing XCU in cluster[%d,%d]\n", x , y );
     1070        _exit();
     1071    }
     1072
     1073    // scan HWIs connected to local XCU
     1074    // for round-robin allocation to local processors
     1075    lpid = 0;
     1076    for ( irq_id = xcu->irq_offset ;
     1077          irq_id < xcu->irq_offset + xcu->irqs ;
     1078          irq_id++ )
     1079    {
     1080        unsigned int type    = irq[irq_id].srctype;
     1081        unsigned int srcid   = irq[irq_id].srcid;
     1082        unsigned int isr     = irq[irq_id].isr & 0xFFFF;
     1083        unsigned int channel = irq[irq_id].channel << 16;
     1084
     1085        if ( (type != IRQ_TYPE_HWI) || (srcid > 31) )
     1086        {
     1087            _printf("\n[BOOT ERROR] Bad IRQ in cluster[%d,%d]\n", x, y );
     1088            _exit();
     1089        }
     1090
     1091        _schedulers[x][y][lpid]->hwi_vector[srcid] = isr | channel | 0x80000000;
     1092
     1093        lpid = (lpid + 1) % nprocs;
     1094    } // end for irqs
     1095
     1096    //////////////////////////////////////////////
     1097    _simple_barrier_wait( &_barrier_all_clusters );
     1098    //////////////////////////////////////////////
     1099
     1100    ////////////////////////////////////////////////////////////////////////
     1101    // Step 2 : Initialise the tasks context. The context of task placed
     1102    //          on  processor P must be stored in the scheduler of P.
     1103    //          This require two nested loops: loop on the tasks, and loop
     1104    //          on the local processors. We complete the scheduler when the
     1105    //          required placement fit one local processor.
    15101106
    15111107    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++)
     
    15131109        // We must set the PTPR depending on the vspace, because the start_vector
    15141110        // and the stack address are defined in virtual space.
    1515         _set_mmu_ptpr( (unsigned int)(_ptabs_paddr[vspace_id][0][0] >> 13) );
     1111        _set_mmu_ptpr( (unsigned int)(_ptabs_paddr[vspace_id][x][y] >> 13) );
    15161112
    15171113        // loop on the tasks in vspace (task_id is the global index in mapping)
     
    15201116             task_id++)
    15211117        {
    1522             // compute the cluster coordinates & local processor index
    1523             unsigned int x          = cluster[task[task_id].clusterid].x;
    1524             unsigned int y          = cluster[task[task_id].clusterid].y;
    1525             unsigned int cluster_xy = (x<<Y_WIDTH) + y;
    1526             unsigned int lpid       = task[task_id].proclocid;                 
    1527 
    1528 #if BOOT_DEBUG_SCHED
    1529 _puts("\n[BOOT DEBUG] Initialise context for task ");
    1530 _puts( task[task_id].name );
    1531 _puts(" in vspace ");
    1532 _puts( vspace[vspace_id].name );
    1533 _puts("\n");
    1534 #endif
    1535             // compute gpid (global processor index) and scheduler base address
    1536             unsigned int gpid = (cluster_xy << P_WIDTH) + lpid;
    1537             psched            = _schedulers[x][y][lpid];
     1118            // get the required task placement coordinates [x,y,p]
     1119            unsigned int req_x      = cluster[task[task_id].clusterid].x;
     1120            unsigned int req_y      = cluster[task[task_id].clusterid].y;
     1121            unsigned int req_p      = task[task_id].proclocid;                 
    15381122
    15391123            // ctx_sr : value required before an eret instruction
     
    15411125
    15421126            // ctx_ptpr : page table physical base address (shifted by 13 bit)
    1543             unsigned int ctx_ptpr = (unsigned int)(_ptabs_paddr[vspace_id][x][y] >> 13);
     1127            unsigned int ctx_ptpr = (_ptabs_paddr[vspace_id][req_x][req_y] >> 13);
    15441128
    15451129            // ctx_ptab : page_table virtual base address
    1546             unsigned int ctx_ptab = _ptabs_vaddr[vspace_id][x][y];
     1130            unsigned int ctx_ptab = _ptabs_vaddr[vspace_id][req_x][req_y];
    15471131
    15481132            // ctx_epc : Get the virtual address of the memory location containing
     
    15561140            unsigned int ctx_sp = vobj[vobj_id].vbase + vobj[vobj_id].length;
    15571141
    1558             // get local task index in scheduler
    1559             unsigned int ltid = psched->tasks;
    1560 
    15611142            // get vspace thread index
    15621143            unsigned int thread_id = task[task_id].trdid;
    15631144
    1564             if (ltid >= IDLE_TASK_INDEX)
     1145            // loop on the local processors
     1146            for ( lpid = 0 ; lpid < nprocs ; lpid++ )
    15651147            {
    1566                 _puts("\n[BOOT ERROR] in boot_schedulers_init() : ");
    1567                 _putd( ltid );
    1568                 _puts(" tasks allocated to processor ");
    1569                 _putd( gpid );
    1570                 _puts(" / max is ");
    1571                 _putd( IDLE_TASK_INDEX );
    1572                 _puts("\n");
     1148                if ( (x == req_x) && (y == req_y) && (req_p == lpid) )   // fit
     1149                {
     1150                    // pointer on selected scheduler
     1151                    psched = _schedulers[x][y][lpid];
     1152
     1153                    // get local task index in scheduler
     1154                    unsigned int ltid = psched->tasks;
     1155
     1156                    // update the "tasks" and "current" fields in scheduler:
     1157                    psched->tasks   = ltid + 1;
     1158                    psched->current = 0;
     1159
     1160                    // initializes the task context
     1161                    psched->context[ltid][CTX_CR_ID]     = 0;
     1162                    psched->context[ltid][CTX_SR_ID]     = ctx_sr;
     1163                    psched->context[ltid][CTX_SP_ID]     = ctx_sp;
     1164                    psched->context[ltid][CTX_EPC_ID]    = ctx_epc;
     1165                    psched->context[ltid][CTX_PTPR_ID]   = ctx_ptpr;
     1166                    psched->context[ltid][CTX_PTAB_ID]   = ctx_ptab;
     1167                    psched->context[ltid][CTX_LTID_ID]   = ltid;
     1168                    psched->context[ltid][CTX_GTID_ID]   = task_id;
     1169                    psched->context[ltid][CTX_TRDID_ID]  = thread_id;
     1170                    psched->context[ltid][CTX_VSID_ID]   = vspace_id;
     1171                    psched->context[ltid][CTX_RUN_ID]    = 1;
     1172
     1173                    psched->context[ltid][CTX_TTY_ID]    = 0xFFFFFFFF;
     1174                    psched->context[ltid][CTX_CMA_FB_ID] = 0xFFFFFFFF;
     1175                    psched->context[ltid][CTX_CMA_RX_ID] = 0xFFFFFFFF;
     1176                    psched->context[ltid][CTX_CMA_TX_ID] = 0xFFFFFFFF;
     1177                    psched->context[ltid][CTX_NIC_RX_ID] = 0xFFFFFFFF;
     1178                    psched->context[ltid][CTX_NIC_TX_ID] = 0xFFFFFFFF;
     1179                    psched->context[ltid][CTX_TIM_ID]    = 0xFFFFFFFF;
     1180                    psched->context[ltid][CTX_HBA_ID]    = 0xFFFFFFFF;
     1181
     1182#if BOOT_DEBUG_SCHED
     1183_printf("\nTask %s in vspace %s allocated to P[%d,%d,%d]\n"
     1184        " - ctx[LTID]  = %d\n"
     1185        " - ctx[SR]    = %x\n"
     1186        " - ctx[SP]    = %x\n"
     1187        " - ctx[EPC]   = %x\n"
     1188        " - ctx[PTPR]  = %x\n"
     1189        " - ctx[PTAB]  = %x\n"
     1190        " - ctx[VSID]  = %d\n"
     1191        " - ctx[TRDID] = %d\n",
     1192        task[task_id].name,
     1193        vspace[vspace_id].name,
     1194        x, y, lpid,
     1195        psched->context[ltid][CTX_LTID_ID],
     1196        psched->context[ltid][CTX_SR_ID],
     1197        psched->context[ltid][CTX_SP_ID],
     1198        psched->context[ltid][CTX_EPC_ID],
     1199        psched->context[ltid][CTX_PTPR_ID],
     1200        psched->context[ltid][CTX_PTAB_ID],
     1201        psched->context[ltid][CTX_VSID_ID],
     1202        psched->context[ltid][CTX_TRDID_ID] );
     1203#endif
     1204                } // end if FIT
     1205            } // end for loop on local procs
     1206        } // end loop on tasks
     1207    } // end loop on vspaces
     1208} // end boot_scheduler_init()
     1209
     1210
     1211/////////////////////////////////////////////////////////////////////////////
     1212// This function loops on all processors in all clusters to display
     1213// the interrupt vectors for each processor.
     1214/////////////////////////////////////////////////////////////////////////////
     1215void boot_sched_irq_display()
     1216{
     1217    unsigned int         cx;
     1218    unsigned int         cy;
     1219    unsigned int         lpid;
     1220    unsigned int         slot;
     1221    unsigned int         entry;
     1222
     1223    mapping_header_t*    header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
     1224    mapping_cluster_t*   cluster = _get_cluster_base(header);
     1225
     1226    static_scheduler_t*  psched;
     1227
     1228    for ( cx = 0 ; cx < X_SIZE ; cx++ )
     1229    {
     1230        for ( cy = 0 ; cy < Y_SIZE ; cy++ )
     1231        {
     1232            unsigned int cluster_id = (cx * Y_SIZE) + cy;
     1233            unsigned int nprocs = cluster[cluster_id].procs;
     1234
     1235            for ( lpid = 0 ; lpid < nprocs ; lpid++ )
     1236            {
     1237                psched = _schedulers[cx][cy][lpid];
     1238       
     1239                _printf("\n[BOOT] scheduler for proc[%d,%d,%d] : ntasks = %d\n",
     1240                        cx , cy , lpid , psched->tasks );
     1241
     1242                for ( slot = 0 ; slot < 32 ; slot++ )
     1243                {
     1244                    entry = psched->hwi_vector[slot];
     1245                    if ( entry & 0x80000000 )
     1246                    _printf(" - HWI %d / isrtype = %d / channel = %d\n",
     1247                            slot , (entry & 0xFFFF) , ((entry >> 16) & 0x7FFF) );
     1248                }
     1249                for ( slot = 0 ; slot < 32 ; slot++ )
     1250                {
     1251                    entry = psched->wti_vector[slot];
     1252                    if ( entry & 0x80000000 )
     1253                    _printf(" - WTI %d / isrtype = %d / channel = %d\n",
     1254                            slot , (entry & 0xFFFF) , ((entry >> 16) & 0x7FFF) );
     1255                }
     1256                for ( slot = 0 ; slot < 32 ; slot++ )
     1257                {
     1258                    entry = psched->pti_vector[slot];
     1259                    if ( entry & 0x80000000 )
     1260                    _printf(" - PTI %d / isrtype = %d / channel = %d\n",
     1261                            slot , (entry & 0xFFFF) , ((entry >> 16) & 0x7FFF) );
     1262                }
     1263            }
     1264        }
     1265    }
     1266}  // end boot_sched_display()
     1267
     1268
     1269/////////////////////////////////////////////////////////////////////////////
     1270// This function complete the schedulers initialisation when the platform
     1271// contains a PIC component in the IO cluster.
     1272// It is executed by P[0][0][0] only.
     1273// It scan HWIs connected to PIC for Round Robin allocation to processors,
     1274// as WTI. It allocates one WTI per processor, starting from P[0,0,0],
     1275// and increments (cluster_id, lpid) as required.
     1276/////////////////////////////////////////////////////////////////////////////
     1277void boot_pic_wti_init()
     1278{
     1279    mapping_header_t*    header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
     1280    mapping_cluster_t*   cluster = _get_cluster_base(header);
     1281    mapping_periph_t*    periph  = _get_periph_base(header);
     1282    mapping_irq_t*       irq     = _get_irq_base(header);
     1283
     1284    unsigned int         periph_id;   // peripheral index in mapping_info
     1285    unsigned int         irq_id;      // irq index in mapping_info
     1286
     1287    // get cluster_io index in mapping
     1288    unsigned int         x_io       = header->x_io; 
     1289    unsigned int         y_io       = header->y_io; 
     1290    unsigned int         cluster_io = (x_io * Y_SIZE) + y_io;
     1291   
     1292    // scan peripherals in cluster_io to find PIC
     1293    mapping_periph_t*    pic = NULL;
     1294
     1295    for ( periph_id = cluster[cluster_io].periph_offset ;
     1296          periph_id < cluster[cluster_io].periph_offset + cluster[cluster_io].periphs;
     1297          periph_id++ )
     1298    {
     1299        if ( periph[periph_id].type == PERIPH_TYPE_PIC )
     1300        {
     1301            pic = &periph[periph_id];
     1302            break;
     1303        }
     1304    }
     1305
     1306    if ( pic == NULL )  return;
     1307
     1308    // initialize WTI channel allocators in all clusters
     1309    unsigned int x;
     1310    unsigned int y;
     1311    for ( x = 0 ; x < X_SIZE ; x++ )
     1312    {
     1313        for ( y = 0 ; y < Y_SIZE ; y++ )
     1314        {
     1315            _wti_channel_alloc[x][y] = NB_PROCS_MAX;
     1316        }
     1317    }
     1318
     1319    // scan IRQS defined in PIC
     1320    unsigned int  cluster_id = 0;
     1321    unsigned int  lpid       = 0;
     1322    unsigned int  cx         = cluster[cluster_id].x;
     1323    unsigned int  cy         = cluster[cluster_id].y;
     1324
     1325    for ( irq_id = pic->irq_offset ;
     1326          irq_id < pic->irq_offset + pic->irqs ;
     1327          irq_id++ )
     1328    {
     1329        // compute next values for cluster_id, lpid, cx, cy
     1330        // if no more WTI allocatable in current cluster
     1331        unsigned int overflow = 0;
     1332
     1333        while ( (lpid >= cluster[cluster_id].procs) ||
     1334                (_wti_channel_alloc[cx][cy] >= 16) )
     1335        {
     1336            cluster_id = (cluster_id + 1) % (X_SIZE*Y_SIZE);
     1337            cx         = cluster[cluster_id].x;
     1338            cy         = cluster[cluster_id].y;
     1339            lpid       = 0;
     1340
     1341            overflow++;
     1342
     1343            if ( overflow > 1024 )
     1344            {
     1345                _printf("\n[BOOT ERROR] Not enough processors for external IRQs\n");
    15731346                _exit();
    15741347            }
    1575 
    1576             // update the "tasks" and "current" fields in scheduler:
    1577             // the first task to execute is task 0 as soon as there is at least
    1578             // one task allocated to processor.
    1579             psched->tasks   = ltid + 1;
    1580             psched->current = 0;
    1581 
    1582             // initializes the task context
    1583             psched->context[ltid][CTX_CR_ID]     = 0;
    1584             psched->context[ltid][CTX_SR_ID]     = ctx_sr;
    1585             psched->context[ltid][CTX_SP_ID]     = ctx_sp;
    1586             psched->context[ltid][CTX_EPC_ID]    = ctx_epc;
    1587             psched->context[ltid][CTX_PTPR_ID]   = ctx_ptpr;
    1588             psched->context[ltid][CTX_PTAB_ID]   = ctx_ptab;
    1589             psched->context[ltid][CTX_LTID_ID]   = ltid;
    1590             psched->context[ltid][CTX_GTID_ID]   = task_id;
    1591             psched->context[ltid][CTX_TRDID_ID]  = thread_id;
    1592             psched->context[ltid][CTX_VSID_ID]   = vspace_id;
    1593             psched->context[ltid][CTX_RUN_ID]    = 1;
    1594 
    1595             psched->context[ltid][CTX_TTY_ID]    = 0xFFFFFFFF;
    1596             psched->context[ltid][CTX_CMA_FB_ID] = 0xFFFFFFFF;
    1597             psched->context[ltid][CTX_CMA_RX_ID] = 0xFFFFFFFF;
    1598             psched->context[ltid][CTX_CMA_TX_ID] = 0xFFFFFFFF;
    1599             psched->context[ltid][CTX_NIC_RX_ID] = 0xFFFFFFFF;
    1600             psched->context[ltid][CTX_NIC_TX_ID] = 0xFFFFFFFF;
    1601             psched->context[ltid][CTX_TIM_ID]    = 0xFFFFFFFF;
    1602             psched->context[ltid][CTX_HBA_ID]    = 0xFFFFFFFF;
     1348        }
     1349        // allocate a WTI to processor defined by (cluster_id,lpid)
     1350        unsigned int type    = irq[irq_id].srctype;
     1351        unsigned int srcid   = irq[irq_id].srcid;
     1352        unsigned int isr     = irq[irq_id].isr & 0xFFFF;
     1353        unsigned int channel = irq[irq_id].channel << 16;
     1354
     1355        if ( (type != IRQ_TYPE_HWI) || (srcid > 31) )
     1356        {
     1357            _printf("\n[BOOT ERROR] in boot_pic_wti_init() Bad IRQ type\n");
     1358            _exit();
     1359        }
     1360
     1361        // get scheduler address for selected processor
     1362        static_scheduler_t* psched = _schedulers[cx][cy][lpid];
     1363
     1364        // update WTI vector for selected processor
     1365        unsigned int index            = _wti_channel_alloc[cx][cy];
     1366        psched->wti_vector[index]     = isr | channel | 0x80000000;
     1367
     1368        // update IRQ fields in mapping for PIC initialisation
     1369        irq[irq_id].dest_id = index;
     1370        irq[irq_id].dest_xy = (cx << Y_WIDTH) + cy;
     1371
     1372        // update pointers
     1373        _wti_channel_alloc[cx][cy] = index + 1;
     1374        lpid                       = lpid + 1;
     1375
     1376    }  // end for IRQs
    16031377
    16041378#if BOOT_DEBUG_SCHED
    1605 _puts("\nTask ");
    1606 _putd( task_id );
    1607 _puts(" allocated to processor[");
    1608 _putd( x );
    1609 _puts(",");
    1610 _putd( y );
    1611 _puts(",");
    1612 _putd( lpid );
    1613 _puts("]\n  - ctx[LTID]   = ");
    1614 _putd( psched->context[ltid][CTX_LTID_ID] );
    1615 _puts("\n  - ctx[SR]     = ");
    1616 _putx( psched->context[ltid][CTX_SR_ID] );
    1617 _puts("\n  - ctx[SP]     = ");
    1618 _putx( psched->context[ltid][CTX_SP_ID] );
    1619 _puts("\n  - ctx[EPC]    = ");
    1620 _putx( psched->context[ltid][CTX_EPC_ID] );
    1621 _puts("\n  - ctx[PTPR]   = ");
    1622 _putx( psched->context[ltid][CTX_PTPR_ID] );
    1623 _puts("\n  - ctx[PTAB]   = ");
    1624 _putx( psched->context[ltid][CTX_PTAB_ID] );
    1625 _puts("\n  - ctx[GTID]   = ");
    1626 _putx( psched->context[ltid][CTX_GTID_ID] );
    1627 _puts("\n  - ctx[VSID]   = ");
    1628 _putx( psched->context[ltid][CTX_VSID_ID] );
    1629 _puts("\n  - ctx[TRDID]  = ");
    1630 _putx( psched->context[ltid][CTX_TRDID_ID] );
    1631 _puts("\n");
    1632 #endif
    1633 
    1634         } // end loop on tasks
    1635     } // end loop on vspaces
    1636 } // end boot_schedulers_init()
    1637 
     1379boot_sched_irq_display();
     1380#endif
     1381
     1382} // end boot_pic_wti_init()
     1383               
    16381384//////////////////////////////////////////////////////////////////////////////////
    16391385// This function loads the map.bin file from block device.
     
    16501396    if ( fd_id == -1 )
    16511397    {
    1652         _puts("\n[BOOT ERROR] : map.bin file not found \n");
     1398        _printf("\n[BOOT ERROR] : map.bin file not found \n");
    16531399        _exit();
    16541400    }
    16551401
    16561402#if BOOT_DEBUG_MAPPING
    1657 _puts("\n[BOOT] map.bin file successfully open at cycle ");
    1658 _putd(_get_proctime());
    1659 _puts("\n");
     1403_printf("\n[BOOT] map.bin file successfully open at cycle %d\n", _get_proctime() );
    16601404#endif
    16611405
     
    16651409    if ( size > SEG_BOOT_MAPPING_SIZE )
    16661410    {
    1667         _puts("\n[BOOT ERROR] : allocated segment too small for map.bin file\n");
     1411        _printf("\n[BOOT ERROR] : allocated segment too small for map.bin file\n");
    16681412        _exit();
    16691413    }
    16701414
    16711415#if BOOT_DEBUG_MAPPING
    1672 _puts("\n[BOOT] map.bin buffer pbase = ");
    1673 _putx( SEG_BOOT_MAPPING_BASE );
    1674 _puts(" / buffer size = ");
    1675 _putx( SEG_BOOT_MAPPING_SIZE );
    1676 _puts(" / file size = ");
    1677 _putx( size );
    1678 _puts("\n");
     1416_printf("\n[BOOT] map.bin buffer pbase = %x / buffer size = %x / file_size = %x\n",
     1417        SEG_BOOT_MAPPING_BASE , SEG_BOOT_MAPPING_SIZE , size );
    16791418#endif
    16801419
     
    16911430    if ( ok == -1 )
    16921431    {
    1693         _puts("\n[BOOT ERROR] : unable to load map.bin file \n");
     1432        _printf("\n[BOOT ERROR] : unable to load map.bin file \n");
    16941433        _exit();
    16951434    }
    16961435
    16971436#if BOOT_DEBUG_MAPPING
    1698 _puts("\n[BOOT] map.bin file successfully loaded at cycle ");
    1699 _putd(_get_proctime());
    1700 _puts("\n");
     1437_printf("\n[BOOT] map.bin file successfully loaded at cycle %d\n", _get_proctime() );
    17011438#endif
    17021439
     
    17101447
    17111448#if BOOT_DEBUG_MAPPING
    1712 unsigned int  word;
    17131449unsigned int  line;
    17141450unsigned int* pointer = (unsigned int*)SEG_BOOT_MAPPING_BASE;
    1715 _puts("\n[BOOT] First block of mapping\n");
     1451_printf("\n[BOOT] First block of mapping\n");
    17161452for ( line = 0 ; line < 8 ; line++ )
    17171453{
    1718     for ( word = 0 ; word < 8 ; word++ )
    1719     {
    1720         _puts(" | ");
    1721         _putx( *(pointer + word) );
    1722     }
    1723     _puts(" |\n");
     1454    _printf(" | %x | %x | %x | %x | %x | %x | %x | %x |\n",
     1455            *(pointer + 0),
     1456            *(pointer + 1),
     1457            *(pointer + 2),
     1458            *(pointer + 3),
     1459            *(pointer + 4),
     1460            *(pointer + 5),
     1461            *(pointer + 6),
     1462            *(pointer + 7) );
     1463
    17241464    pointer = pointer + 8;
    17251465}
    17261466#endif
    1727         _puts("\n[BOOT ERROR] Illegal mapping signature: ");
    1728         _putx(header->signature);
    1729         _puts("\n");
     1467        _printf("\n[BOOT ERROR] Illegal mapping signature: %x\n", header->signature );
    17301468        _exit();
    17311469    }
    17321470
    17331471#if BOOT_DEBUG_MAPPING
    1734 _puts("\n[BOOT] map.bin file checked at cycle ");
    1735 _putd(_get_proctime());
    1736 _puts("\n");
     1472_printf("\n[BOOT] map.bin file checked at cycle %d\n", _get_proctime() );
    17371473#endif
    17381474
     
    17701506
    17711507#if BOOT_DEBUG_ELF
    1772 _puts("\n[BOOT DEBUG] Start searching file ");
    1773 _puts( pathname );
    1774 _puts(" at cycle ");
    1775 _putd( _get_proctime() );
    1776 _puts("\n");
     1508_printf("\n[BOOT] Start searching file %s at cycle %d\n",
     1509        pathname, _get_proctime() );
    17771510#endif
    17781511
     
    17831516    if ( fd_id < 0 )
    17841517    {
    1785         _puts("\n[BOOT ERROR] load_one_elf_file() : ");
    1786         _puts( pathname );
    1787         _puts(" not found\n");
     1518        _printf("\n[BOOT ERROR] load_one_elf_file() : %s not found\n", pathname );
    17881519        _exit();
    17891520    }
     
    17921523    if ( fat.fd[fd_id].file_size > GIET_ELF_BUFFER_SIZE )
    17931524    {
    1794         _puts("\n[BOOT ERROR] in load_one_elf_file() : ");
    1795         _puts( pathname );
    1796         _puts(" size = ");
    1797         _putx( fat.fd[fd_id].file_size );
    1798         _puts("\n exceeds the GIET_ELF_BUFFERSIZE = ");
    1799         _putx( GIET_ELF_BUFFER_SIZE );
    1800         _puts("\n");
     1525        _printf("\n[BOOT ERROR] in load_one_elf_file() : %s / size = %x "
     1526                "larger than GIET_ELF_BUFFER_SIZE = %x\n",
     1527                pathname , fat.fd[fd_id].file_size , GIET_ELF_BUFFER_SIZE );
    18011528        _exit();
    18021529    }
     
    18141541                   0 ) != nsectors )
    18151542    {
    1816         _puts("\n[BOOT ERROR] load_one_elf_file() : unexpected EOF for file ");
    1817         _puts( pathname );
    1818         _puts("\n");   
     1543        _printf("\n[BOOT ERROR] load_one_elf_file() : unexpected EOF for file %s\n",
     1544                pathname );
    18191545        _exit();
    18201546    }
     
    18281554         (elf_header_ptr->e_ident[EI_MAG3] != ELFMAG3) )
    18291555    {
    1830         _puts("\n[BOOT ERROR] load_elf() : file ");
    1831         _puts( pathname );
    1832         _puts(" does not use ELF format\n");   
     1556        _printf("\n[BOOT ERROR] load_elf() : file %s does not use ELF format\n",
     1557                pathname );
    18331558        _exit();
    18341559    }
     
    18381563    if( pht_index == 0 )
    18391564    {
    1840         _puts("\n[BOOT ERROR] load_one_elf_file() : file ");
    1841         _puts( pathname );
    1842         _puts(" does not contain loadable segment\n");   
     1565        _printf("\n[BOOT ERROR] load_one_elf_file() : file %s "
     1566                "does not contain loadable segment\n", pathname );
    18431567        _exit();
    18441568    }
     
    18471571    // get number of segments
    18481572    unsigned int nsegments   = elf_header_ptr->e_phnum;
    1849 
    1850     _puts("\n[BOOT] File ");
    1851     _puts( pathname );
    1852     _puts(" loaded at cycle ");
    1853     _putd( _get_proctime() );
    1854     _puts("\n");
    18551573
    18561574    // Loop on loadable segments in the .elf file
     
    18661584
    18671585#if BOOT_DEBUG_ELF
    1868 _puts(" - segment ");
    1869 _putd( seg_id );
    1870 _puts(" / vaddr = ");
    1871 _putx( seg_vaddr );
    1872 _puts(" / file_size = ");
    1873 _putx( seg_filesz );
    1874 _puts("\n");
     1586_printf("\n[BOOT] Segment %d : vaddr = %x / size = %x\n",
     1587        seg_id , seg_vaddr , seg_filesz );
    18751588#endif
    18761589
    18771590            if( seg_memsz < seg_filesz )
    18781591            {
    1879                 _puts("\n[BOOT ERROR] load_one_elf_file() : segment at vaddr = ");
    1880                 _putx( seg_vaddr );
    1881                 _puts(" in file ");
    1882                 _puts( pathname );
    1883                 _puts(" has memsz < filesz \n");   
     1592                _printf("\n[BOOT ERROR] load_one_elf_file() : segment at vaddr = %x"
     1593                        " in file %s has memsize < filesize \n", seg_vaddr, pathname );
    18841594                _exit();
    18851595            }
     
    18891599            {
    18901600                unsigned int i;
    1891                 for( i = seg_filesz ; i < seg_memsz ; i++ ) boot_elf_buffer[i+seg_offset] = 0;
     1601                for( i = seg_filesz ; i < seg_memsz ; i++ )
     1602                   boot_elf_buffer[i+seg_offset] = 0;
    18921603            }
    18931604
     
    19221633                   
    19231634#if BOOT_DEBUG_ELF
    1924 _puts("   loaded into vseg ");
    1925 _puts( vseg[vseg_id].name );
    1926 _puts(" at paddr = ");
    1927 _putl( seg_paddr );
    1928 _puts(" (buffer size = ");
    1929 _putx( seg_size );
    1930 _puts(")\n");
     1635_printf("   loaded into vseg %s at paddr = %l / buffer size = %x\n",
     1636        vseg[vseg_id].name , seg_paddr , seg_size );
    19311637#endif
    19321638                    // check vseg size
    19331639                    if ( seg_size < seg_filesz )
    19341640                    {
    1935                         _puts("\n[BOOT ERROR] in load_one_elf_file()\n");
    1936                         _puts("vseg ");
    1937                         _puts( vseg[vseg_id].name );
    1938                         _puts(" is to small for loadable segment ");
    1939                         _putx( seg_vaddr );
    1940                         _puts(" in file ");
    1941                         _puts( pathname );
    1942                         _puts(" \n");   
     1641                        _printf("\n[BOOT ERROR] in load_one_elf_file() : vseg %s "
     1642                                "is to small for loadable segment %x in file %s\n",
     1643                                vseg[vseg_id].name , seg_vaddr , pathname );
    19431644                        _exit();
    19441645                    }
     
    19661667            if ( found == 0 )
    19671668            {
    1968                 _puts("\n[BOOT ERROR] in load_one_elf_file()\n");
    1969                 _puts("vseg for loadable segment ");
    1970                 _putx( seg_vaddr );
    1971                 _puts(" in file ");
    1972                 _puts( pathname );
    1973                 _puts(" not found: \n");   
    1974                 _puts(" check consistency between the .py and .ld files...\n");
     1669                _printf("\n[BOOT ERROR] in load_one_elf_file() : vseg for loadable "
     1670                        "segment %x in file %s not found "
     1671                        "check consistency between the .py and .ld files\n",
     1672                        seg_vaddr, pathname );
    19751673                _exit();
    19761674            }
     
    19801678    // close .elf file
    19811679    _fat_close( fd_id );
     1680
     1681    _printf("\n[BOOT] File %s loaded at cycle %d\n",
     1682            pathname , _get_proctime() );
    19821683
    19831684} // end load_one_elf_file()
     
    20181719    if (found == 0)
    20191720    {
    2020         _puts("[BOOT ERROR] boot_elf_load() : kernel.elf file not found\n");
     1721        _printf("\n[BOOT ERROR] boot_elf_load() : kernel.elf file not found\n");
    20211722        _exit();
    20221723    }
     
    20471748        if (found == 0)
    20481749        {
    2049             _puts("[BOOT ERROR] boot_elf_load() : .elf file not found for vspace ");
    2050             _puts( vspace[vspace_id].name );
    2051             _puts("\n");
     1750            _printf("\n[BOOT ERROR] boot_elf_load() : "
     1751                    ".elf file not found for vspace %s\n", vspace[vspace_id].name );
    20521752            _exit();
    20531753        }
     
    20901790
    20911791#if BOOT_DEBUG_PERI
    2092 _puts("\n[BOOT DEBUG] Peripherals initialisation in cluster[");
    2093 _putd( x );
    2094 _puts(",");
    2095 _putd( y );
    2096 _puts("]\n");
     1792_printf("\n[BOOT] Peripherals initialisation in cluster[%d,%d]\n", x , y );
    20971793#endif
    20981794
     
    21711867
    21721868#if BOOT_DEBUG_PERI
    2173 unsigned int address = _pic_get_register( channel_id, IOPIC_ADDRESS );
    2174 unsigned int extend  = _pic_get_register( channel_id, IOPIC_EXTEND  );
    2175 _puts("    hwi_index = ");
    2176 _putd( hwi_id );
    2177 _puts(" / wti_index = ");
    2178 _putd( wti_id );
    2179 _puts(" / vaddr = ");
    2180 _putx( vaddr );
    2181 _puts(" in cluster[");
    2182 _putd( cluster_xy >> Y_WIDTH );
    2183 _puts(",");
    2184 _putd( cluster_xy & ((1<<Y_WIDTH)-1) );
    2185 _puts("] / checked_xcu_paddr = ");
    2186 _putl( (paddr_t)address + (((paddr_t)extend)<<32) );
    2187 _puts("\n");
     1869_printf("[BOOT] PIC : hwi_index = %d => wti_index = %d for XCU[%d,%d]\n",
     1870        hwi_id , wti_id , cluster_xy >> Y_WIDTH , cluster_xy & ((1<<Y_WIDTH)-1) );
    21881871#endif
    21891872                    }
     
    21941877
    21951878#if BOOT_DEBUG_PERI
    2196 _puts("\n[BOOT DEBUG] Coprocessors initialisation in cluster[");
    2197 _putd( x );
    2198 _puts(",");
    2199 _putd( y );
    2200 _puts("]\n");
     1879_printf("\n[BOOT] Coprocessors initialisation in cluster[%d,%d]\n", x , y );
    22011880#endif
    22021881
     
    22061885              cluster[cluster_id].coprocs; coproc_id++ )
    22071886        {
    2208 
    2209 #if BOOT_DEBUG_PERI
    2210 _puts("- coprocessor name : ");
    2211 _puts(coproc[coproc_id].name);
    2212 _puts(" / nb ports = ");
    2213 _putd((unsigned int) coproc[coproc_id].ports);
    2214 _puts("\n");
    2215 #endif
    22161887            // loop on the coprocessor ports
    22171888            for ( cp_port_id = coproc[coproc_id].port_offset;
     
    22411912                              cp_port[cp_port_id].direction,
    22421913                              pbase );
    2243 #if BOOT_DEBUG_PERI
    2244 _puts("     port direction: ");
    2245 _putd( (unsigned int)cp_port[cp_port_id].direction );
    2246 _puts(" / mwmr_channel_pbase = ");
    2247 _putl( pbase );
    2248 _puts(" / name = ");
    2249 _puts(vobj[vobj_id].name);
    2250 _puts("\n");
    2251 #endif
     1914
    22521915            } // end for cp_ports
    22531916        } // end for coprocs
     
    22551918} // end boot_peripherals_init()
    22561919
    2257 /////////////////////////////////////////////////////////////////////////
    2258 // This function initialises the physical memory allocators in each
    2259 // cluster containing a RAM pseg.
    2260 // it is handled by the processor[x][y][0]
    2261 /////////////////////////////////////////////////////////////////////////
    2262 void boot_pmem_init()
     1920///////////////////////////////////////////////////////////////////////////////////////
     1921// This function is executed in parallel by all processors[x][y][0].
     1922// It initialises the physical memory allocator in each cluster containing a RAM pseg.
     1923///////////////////////////////////////////////////////////////////////////////////////
     1924void boot_pmem_init( unsigned int cx,
     1925                     unsigned int cy )
    22631926{
    22641927    mapping_header_t*  header     = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
     
    22661929    mapping_pseg_t*    pseg       = _get_pseg_base(header);
    22671930
    2268     unsigned int cluster_id;
    22691931    unsigned int pseg_id;
    22701932    unsigned int procid     = _get_procid();
    2271     unsigned int x_cluster  = (procid >> (Y_WIDTH + P_WIDTH)) & ((1<<X_WIDTH)-1);
    2272     unsigned int y_cluster  = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
    22731933    unsigned int lpid       = procid & ((1<<P_WIDTH)-1);
    2274     if(lpid)
    2275     {
    2276         _puts("[BOOT ERROR] boot_pmem_init() : error local processor id\n");
     1934
     1935    if( lpid )
     1936    {
     1937        _printf("\n[BOOT ERROR] boot_pmem_init() : "
     1938        "P[%d][%d][%d] should not execute it\n", cx, cy, lpid );
    22771939        _exit();
    2278     }      // scan all clusters
    2279 
    2280     cluster_id = x_cluster * Y_SIZE + y_cluster;
    2281     // scan the psegs in cluster to find first pseg of type RAM
    2282     unsigned int pseg_min = cluster[cluster_id].pseg_offset;
    2283     unsigned int pseg_max = pseg_min + cluster[cluster_id].psegs;
     1940    }   
     1941
     1942    // scan the psegs in local cluster to find  pseg of type RAM
     1943    unsigned int found      = 0;
     1944    unsigned int cluster_id = cx * Y_SIZE + cy;
     1945    unsigned int pseg_min   = cluster[cluster_id].pseg_offset;
     1946    unsigned int pseg_max   = pseg_min + cluster[cluster_id].psegs;
    22841947    for ( pseg_id = pseg_min ; pseg_id < pseg_max ; pseg_id++ )
    22851948    {
    22861949        if ( pseg[pseg_id].type == PSEG_TYPE_RAM )
    22871950        {
    2288             unsigned int x    = cluster[cluster_id].x;
    2289             unsigned int y    = cluster[cluster_id].y;
    2290             if(x != x_cluster || y != y_cluster)
    2291             {
    2292                 _puts("[BOOT ERROR] boot_pmem_init() : error cluster id \n");
    2293                 _exit();
    2294             } 
    22951951            unsigned int base = (unsigned int)pseg[pseg_id].base;
    22961952            unsigned int size = (unsigned int)pseg[pseg_id].length;
    2297             _pmem_alloc_init( x, y, base, size );
     1953            _pmem_alloc_init( cx, cy, base, size );
     1954            found = 1;
    22981955
    22991956#if BOOT_DEBUG_PT
    2300 _get_lock(&lock_tty);
    2301 _puts("\n[BOOT DEBUG] pmem allocator initialised in cluster[");
    2302 _putd( x );
    2303 _puts(",");
    2304 _putd( y );
    2305 _puts("] base = ");
    2306 _putx( base );
    2307 _puts(" / size = ");
    2308 _putx( size );
    2309 _puts("\n");
    2310 _release_lock(&lock_tty);
     1957_printf("\n[BOOT] pmem allocator initialised in cluster[%d][%d]"
     1958        " : base = %x / size = %x\n", cx , cy , base , size );
    23111959#endif
    23121960            break;
    23131961        }
    23141962    }
     1963
     1964    if ( found == 0 )
     1965    {
     1966        _printf("\n[BOOT ERROR] boot_pmem_init() : no RAM in cluster[%d][%d]\n",
     1967              cx , cy );
     1968        _exit();
     1969    }   
    23151970} // end boot_pmem_init()
    23161971 
    23171972/////////////////////////////////////////////////////////////////////////
    23181973// This function is the entry point of the boot code for all processors.
    2319 // Most of this code is executed by Processor 0 only.
    23201974/////////////////////////////////////////////////////////////////////////
    23211975void boot_init()
     
    23231977    mapping_header_t*  header     = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
    23241978    mapping_cluster_t* cluster    = _get_cluster_base(header);
     1979
    23251980    unsigned int       gpid       = _get_procid();
    2326     unsigned int       clusterid, p;
    2327 
    2328     if ( gpid == 0 )    // only Processor 0 does it
    2329     {
    2330         _puts("\n[BOOT] boot_init start at cycle ");
    2331         _putd(_get_proctime());
    2332         _puts("\n");
     1981    unsigned int       cx         = gpid >> (Y_WIDTH + P_WIDTH);
     1982    unsigned int       cy         = (gpid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
     1983    unsigned int       lpid       = gpid & ((1 << P_WIDTH) -1);
     1984    unsigned int       cluster_id = (cx * Y_SIZE) + cy;
     1985
     1986    // Phase ONE : only P[0][0][0] execute it
     1987    if ( gpid == 0 )   
     1988    {
     1989        unsigned int cid;  // index for loops
     1990
     1991        // initialises the TTY0 spin lock
     1992        _spin_lock_init( &_tty0_spin_lock );
     1993
     1994        _printf("\n[BOOT] P[0,0,0] starts at cycle %d\n", _get_proctime() );
    23331995
    23341996        // initialises the FAT
    23351997        _fat_init( IOC_BOOT_MODE );
    23361998
    2337         _puts("\n[BOOT] Fat initialised at cycle ");
    2338         _putd(_get_proctime());
    2339         _puts("\n");
    2340         // Load the map.bin file into memory and check it
     1999        _printf("\n[BOOT] FAT initialised at cycle %d\n", _get_proctime() );
     2000
     2001        // Load the map.bin file into memory
    23412002        boot_mapping_init();
    23422003
    2343         _puts("\n[BOOT] Mapping \"");
    2344         _puts( header->name );
    2345         _puts("\" loaded at cycle ");
    2346         _putd(_get_proctime());
    2347         _puts("\n");
    2348 
    2349         _barrier_init(&barrier_boot, X_SIZE*Y_SIZE);
    2350 
    2351         for ( clusterid = 1 ; clusterid < X_SIZE*Y_SIZE ; clusterid++ )
    2352         {
    2353             unsigned int x          = cluster[clusterid].x;
    2354             unsigned int y          = cluster[clusterid].y;
    2355             unsigned int cluster_xy = (x<<Y_WIDTH) + y;
    2356 
    2357             _xcu_send_wti_paddr( cluster_xy, 0, (unsigned int)boot_entry );
    2358         }
    2359     }
    2360     //Parallel phase to construct the ptab by each processor[x][y][0]
    2361     if( (gpid & ((1 << P_WIDTH) -1)) == 0)
    2362     {
    2363         // Initializes the physical memory allocators
    2364         boot_pmem_init();
    2365         // Build ge tables
    2366         boot_ptabs_init();
    2367         //wait for all processors finished the work
    2368         _barrier_wait(&barrier_boot);
    2369 
    2370         if( gpid ) while( boot_init_ok == 0);
    2371     }
    2372 
    2373     if ( gpid == 0 )    // only Processor 0 does it
    2374     {
    2375         _puts("\n[BOOT] Physical memory allocators and Page table initialized at cycle ");
    2376         _putd(_get_proctime());
    2377         _puts("\n");
    2378 
    2379         // Activate MMU for proc [0,0,0]
    2380         _set_mmu_ptpr( (unsigned int)(_ptabs_paddr[0][0][0]>>13) );
     2004        _printf("\n[BOOT] Mapping %s loaded at cycle %d\n",
     2005                header->name , _get_proctime() );
     2006
     2007        // initialises the barrier for all clusters containing processors
     2008        unsigned int nclusters = 0;
     2009        for ( cid = 0 ; cid < X_SIZE*Y_SIZE ; cid++ )
     2010        {
     2011            if ( cluster[cid].procs ) nclusters++ ;
     2012        }
     2013
     2014        _simple_barrier_init( &_barrier_all_clusters , nclusters );
     2015
     2016        // wake up all processors P[x][y][0]
     2017        for ( cid = 1 ; cid < X_SIZE*Y_SIZE ; cid++ )
     2018        {
     2019            unsigned int x          = cluster[cid].x;
     2020            unsigned int y          = cluster[cid].y;
     2021            unsigned int cluster_xy = (x << Y_WIDTH) + y;
     2022
     2023            if ( cluster[cid].procs )
     2024            {
     2025                unsigned long long paddr = (((unsigned long long)cluster_xy)<<32) +
     2026                                           SEG_XCU_BASE + XCU_REG( XCU_WTI_REG , 0 );
     2027
     2028                _physical_write( paddr , (unsigned int)boot_entry );
     2029            }
     2030        }
     2031
     2032        _printf("\n[BOOT] Processors P[x,y,0] start at cycle %d\n", _get_proctime() );
     2033    }
     2034
     2035    // Phase TWO : All processors P[x][y][0] execute it in parallel
     2036    if( lpid == 0 )
     2037    {
     2038        // Initializes physical memory allocator in cluster[cx][cy]
     2039        boot_pmem_init( cx , cy );
     2040
     2041        // Build page table in cluster[cx][cy]
     2042        boot_ptab_init( cx , cy );
     2043
     2044        //////////////////////////////////////////////
     2045        _simple_barrier_wait( &_barrier_all_clusters );
     2046        //////////////////////////////////////////////
     2047
     2048        // P[0][0][0] complete page tables with vsegs
     2049        // mapped in clusters without processors
     2050        if ( gpid == 0 )   
     2051        {
     2052            // complete page tables initialisation
     2053            boot_ptab_extend();
     2054
     2055            _printf("\n[BOOT] Physical memory allocators and page tables"
     2056                    " initialized at cycle %d\n", _get_proctime() );
     2057        }
     2058
     2059        //////////////////////////////////////////////
     2060        _simple_barrier_wait( &_barrier_all_clusters );
     2061        //////////////////////////////////////////////
     2062
     2063        // All processors P[x,y,0] activate MMU (using local PTAB)
     2064        _set_mmu_ptpr( (unsigned int)(_ptabs_paddr[0][cx][cy]>>13) );
    23812065        _set_mmu_mode( 0xF );
    2382 
    2383         _puts("\n[BOOT] Processor[0,0,0] : MMU activation at cycle ");
    2384         _putd(_get_proctime());
    2385         _puts("\n");
    2386 
    2387         // Initialise private vobjs in vspaces
    2388         boot_vobjs_init();
    2389 
    2390         _puts("\n[BOOT] Private vobjs initialised at cycle ");
    2391         _putd(_get_proctime());
    2392         _puts("\n");
    2393  
    2394         // Initialise schedulers
    2395         boot_schedulers_init();
    2396 
    2397         _puts("\n[BOOT] Schedulers initialised at cycle ");
    2398         _putd(_get_proctime());
    2399         _puts("\n");
    24002066       
    2401         // Set CP0_SCHED register for proc [0,0,0]
    2402         _set_sched( (unsigned int)_schedulers[0][0][0] );
    2403 
    2404         // Initialise non replicated peripherals
    2405         boot_peripherals_init();
    2406 
    2407         _puts("\n[BOOT] Non replicated peripherals initialised at cycle ");
    2408         _putd(_get_proctime());
    2409         _puts("\n");
    2410 
    2411         // Loading all .elf files
    2412         boot_elf_load();
    2413 
    2414         // wake up the processors which has constructed the ptab before
    2415         boot_init_ok = 1;
    2416 
    2417         for ( clusterid = 0 ; clusterid < X_SIZE*Y_SIZE ; clusterid++ )
    2418         {
    2419             unsigned int nprocs     = cluster[clusterid].procs;
    2420             unsigned int x          = cluster[clusterid].x;
    2421             unsigned int y          = cluster[clusterid].y;
    2422             unsigned int cluster_xy = (x<<Y_WIDTH) + y;
    2423 
    2424             for ( p = 1 ; p < nprocs; p++ )
     2067        // Each processor P[x,y,0] initialises all schedulers in cluster[x,y]
     2068        boot_scheduler_init( cx , cy );
     2069
     2070        // Each processor P[x][y][0] initialises its CP0_SCHED register
     2071        _set_sched( (unsigned int)_schedulers[cx][cy][0] );
     2072
     2073        //////////////////////////////////////////////
     2074        _simple_barrier_wait( &_barrier_all_clusters );
     2075        //////////////////////////////////////////////
     2076       
     2077        // Processor P[0,0,0] completes schedulers with PIC-WTI
     2078        // initialises external peripherals and load .elf files.
     2079        if ( gpid == 0 )
     2080        {
     2081            // complete schedulers initialisation
     2082            boot_pic_wti_init();
     2083
     2084            _printf("\n[BOOT] Schedulers initialised at cycle %d\n", _get_proctime() );
     2085
     2086            // initialize non replicated peripherals
     2087            boot_peripherals_init();
     2088
     2089            _printf("\n[BOOT] Peripherals initialised at cycle %d\n", _get_proctime() );
     2090
     2091            // Loading all .elf files
     2092            boot_elf_load();
     2093        }
     2094/* 
     2095        // Each processor P[x][y][0] checks sequencially its local page table
     2096        unsigned int seq_x;
     2097        unsigned int seq_y;
     2098        for ( seq_x = 0 ; seq_x < X_SIZE ; seq_x++ )
     2099        {
     2100            for ( seq_y = 0 ; seq_y < Y_SIZE ; seq_y++ )
    24252101            {
    2426                 _xcu_send_wti( cluster_xy, p, (unsigned int)boot_entry );
     2102                if ( (cx == seq_x) && (cy == seq_y) ) boot_ptab_check( cx , cy );
     2103               
     2104                //////////////////////////////////////////////
     2105                _simple_barrier_wait( &_barrier_all_clusters );
     2106                //////////////////////////////////////////////
    24272107            }
    24282108        }
    2429     }  // end monoprocessor boot
    2430 
    2431     ///////////////////////////////////////////////////////////////////////////////
    2432     //            Parallel execution starts actually here
    2433     ///////////////////////////////////////////////////////////////////////////////
    2434 
    2435     // all processor initialise the SCHED register
    2436     // from the _schedulers[x][y][lpid array]
    2437     unsigned int cluster_xy = gpid >> P_WIDTH;
    2438     unsigned int lpid       = gpid & ((1<<P_WIDTH)-1);
    2439     unsigned int x          = cluster_xy >> Y_WIDTH;
    2440     unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
    2441     _set_sched( (unsigned int)_schedulers[x][y][lpid] );
    2442 
    2443     // all processors (but Proc[0,0,0]) activate MMU
    2444     if ( gpid != 0 )
    2445     {
    2446         _set_mmu_ptpr( (unsigned int)(_ptabs_paddr[0][x][y]>>13) );
     2109*/         
     2110        //////////////////////////////////////////////
     2111        _simple_barrier_wait( &_barrier_all_clusters );
     2112        //////////////////////////////////////////////
     2113       
     2114        // each processor P[x][y][0] wake up other processors in same cluster
     2115        unsigned int cluster_xy = (cx << Y_WIDTH) + cy;
     2116        unsigned int p;
     2117        for ( p = 1 ; p < cluster[cluster_id].procs ; p++ )
     2118        {
     2119            _xcu_send_wti( cluster_xy , p , (unsigned int)boot_entry );
     2120        }
     2121
     2122        if ( gpid == 0 )    // only P[0][0][0] makes display
     2123        _printf("\n[BOOT] All processors start at cycle %d\n", _get_proctime() );
     2124    }
     2125
     2126    // Other processors than P[x][y][0] activate MMU (using local PTAB)
     2127    if ( lpid != 0 )
     2128    {
     2129        _set_mmu_ptpr( (unsigned int)(_ptabs_paddr[0][cx][cy]>>13) );
    24472130        _set_mmu_mode( 0xF );
    24482131    }
    24492132
    2450     // all processors reset BEV bit in the status register to use
    2451     // the GIET_VM exception handler instead of the PRELOADER exception handler
     2133    // All processors set CP0_SCHED register
     2134    _set_sched( (unsigned int)_schedulers[cx][cy][lpid] );
     2135
     2136    // All processors reset BEV bit in SR to use GIET_VM exception handler
    24522137    _set_sr( 0 );
    24532138
    2454     // all processors jump to kernel_init
    2455     // using the address defined in the giet_vsegs.ld file
     2139    // All processors jump to kernel_init
    24562140    unsigned int kernel_entry = (unsigned int)&kernel_init_vbase;
    24572141    asm volatile( "jr   %0" ::"r"(kernel_entry) );
Note: See TracChangeset for help on using the changeset viewer.