source: soft/giet_vm/giet_boot/boot.c @ 457

Last change on this file since 457 was 452, checked in by alain, 10 years ago

Update the boot.c file to initialise the new slots in task context.

File size: 83.4 KB
RevLine 
[412]1/////////////////////////////////////////////////////////////////////////////////////////
[258]2// File     : boot.c
3// Date     : 01/11/2013
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6//////////////////////////////////////////////////////////////////////////////////////////
7// The boot.c file is part of the GIET-VM nano-kernel.
8//
9// This nano-kernel has been written for the MIPS32 processor.
[359]10// The virtual adresses are on 32 bits and use the (unsigned int) type. The
[258]11// physicals addresses can have up to 40 bits, and use the  (unsigned long long) type.
[412]12// It natively supports clusterised shared memory multi-processors architectures,
[263]13// where each processor is identified by a composite index (cluster_xy, local_id),
[258]14// and where there is one physical memory bank per cluster.
15//
[359]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,
[258]18// - build the various page tables (one page table per vspace)
19// - initialize the shedulers (one scheduler per processor)
20//
21// 1) The binary files to be loaded are:
22//    - the "map.bin" file contains the hardware architecture description and the
23//      mapping directives. It must be stored in the the seg_boot_mapping segment
[321]24//      (at address SEG_BOOT_MAPPING_BASE defined in hard_config.h file).
[258]25//    - the "sys.elf" file contains the kernel binary code and data.
26//    - the various "application.elf" files.
27//
28// 2) The map.bin file contains the binary representation of the map.xml file defining:
29//    - the hardware architecture: number of clusters, number or processors,
30//      size of the memory segments, and peripherals in each cluster.
31//    - The structure of the various multi-threaded software applications:
32//      number of tasks, communication channels.
[309]33//    - The mapping: grouping of virtual objects (vobj) in the virtual segments (vseg),
[258]34//      placement of virtual segments (vseg) in the physical segments (pseg), placement
35//      of software tasks on the processors,
36//
37// 3) The GIET-VM uses the paged virtual memory to provides two services:
38//    - classical memory protection, when several independant applications compiled
39//      in different virtual spaces are executing on the same hardware platform.
[412]40//    - data placement in NUMA architectures, to control the placement
41//      of the software objects (vsegs) on the physical memory banks (psegs).
[258]42//
[412]43//    The max number of vspaces (GIET_NB_VSPACE_MAX) is a configuration parameter.
[258]44//    The page table are statically build in the boot phase, and they do not
[412]45//    change during execution.
46//    The GIET_VM uses both small pages (4 Kbytes), and big pages (2 Mbytes).
[258]47//
48//    Each page table (one page table per virtual space) is monolithic, and contains
[412]49//    one PT1 (8 Kbytes) and a variable number of PT2s (4 Kbytes each). For each vspace,
50//    the numberof PT2s is defined by the size of the PTAB vobj in the mapping.
51//    The PT1 is indexed by the ix1 field (11 bits) of the VPN. Each entry is 32 bits.
52//    A PT2 is indexed the ix2 field (9 bits) of the VPN. Each entry is a double word.
53//    The first word contains the flags, the second word contains the PPN.
54//
55//    The page tables can be distributed in all clusters.
[263]56///////////////////////////////////////////////////////////////////////////////////////
57// Implementation Notes:
58//
59// 1) The cluster_id variable is a linear index in the mapping_info array of clusters.
60//    We use the cluster_xy variable for the tological index = x << Y_WIDTH + y
[412]61//
[263]62///////////////////////////////////////////////////////////////////////////////////////
[258]63
[263]64#include <giet_config.h>
[436]65#include <mapping_info.h>
[258]66#include <mwmr_channel.h>
67#include <barrier.h>
68#include <memspace.h>
69#include <tty_driver.h>
70#include <xcu_driver.h>
[347]71#include <bdv_driver.h>
[258]72#include <dma_driver.h>
73#include <cma_driver.h>
74#include <nic_driver.h>
75#include <ioc_driver.h>
[299]76#include <iob_driver.h>
[295]77#include <pic_driver.h>
[258]78#include <mwr_driver.h>
79#include <ctx_handler.h>
80#include <irq_handler.h>
81#include <vmem.h>
[412]82#include <pmem.h>
[258]83#include <utils.h>
84#include <elf-types.h>
85
86// for boot FAT initialisation
87#include <fat32.h>
88
89#include <mips32_registers.h>
90#include <stdarg.h>
91
[263]92#if !defined(X_SIZE)
[359]93# error: The X_SIZE value must be defined in the 'hard_config.h' file !
[258]94#endif
95
[263]96#if !defined(Y_SIZE)
[359]97# error: The Y_SIZE value must be defined in the 'hard_config.h' file !
[263]98#endif
99
100#if !defined(X_WIDTH)
[359]101# error: The X_WIDTH value must be defined in the 'hard_config.h' file !
[263]102#endif
103
104#if !defined(Y_WIDTH)
[359]105# error: The Y_WIDTH value must be defined in the 'hard_config.h' file !
[263]106#endif
107
[321]108#if !defined(SEG_BOOT_MAPPING_BASE)
[359]109# error: The SEG_BOOT_MAPPING_BASE value must be defined in the hard_config.h file !
[321]110#endif
111
[359]112#if !defined(NB_PROCS_MAX)
113# error: The NB_PROCS_MAX value must be defined in the 'hard_config.h' file !
[321]114#endif
115
[359]116#if !defined(GIET_NB_VSPACE_MAX)
117# error: The GIET_NB_VSPACE_MAX value must be defined in the 'giet_config.h' file !
[321]118#endif
119
[359]120#if !defined(GIET_ELF_BUFFER_SIZE)
121# error: The GIET_ELF_BUFFER_SIZE value must be defined in the giet_config.h file !
[258]122#endif
123
124////////////////////////////////////////////////////////////////////////////
125//      Global variables for boot code
126////////////////////////////////////////////////////////////////////////////
127
[366]128extern void boot_entry();
129
[412]130// FAT internal representation for boot code 
131__attribute__((section (".bootdata"))) 
132fat32_fs_t             fat   __attribute__((aligned(512)));
[258]133
[412]134// Temporaty buffer used to load one complete .elf file 
[258]135__attribute__((section (".bootdata"))) 
[412]136char                   boot_elf_buffer[GIET_ELF_BUFFER_SIZE] __attribute__((aligned(512)));
[258]137
[412]138// Physical memory allocators array (one per cluster)
[258]139__attribute__((section (".bootdata"))) 
[412]140pmem_alloc_t           boot_pmem_alloc[X_SIZE][Y_SIZE];
[258]141
[412]142// Schedulers virtual base addresses array (one per processor)
[258]143__attribute__((section (".bootdata"))) 
[412]144static_scheduler_t*    _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX];
[258]145
[412]146// Page tables virtual base addresses array (one per vspace)
[258]147__attribute__((section (".bootdata"))) 
[412]148unsigned int           _ptabs_vaddr[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
[258]149
[412]150// Page tables physical base addresses (one per vspace and per cluster)
[263]151__attribute__((section (".bootdata"))) 
[412]152paddr_t                _ptabs_paddr[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
[258]153
[412]154// Page tables pt2 allocators (one per vspace and per cluster)
[359]155__attribute__((section (".bootdata"))) 
[412]156unsigned int           _ptabs_next_pt2[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
[263]157
[412]158// Page tables max_pt2  (same value for all page tables)
159__attribute__((section (".bootdata"))) 
160unsigned int           _ptabs_max_pt2;
161
[258]162/////////////////////////////////////////////////////////////////////
163// This function checks consistence beween the  mapping_info data
164// structure (soft), and the giet_config file (hard).
165/////////////////////////////////////////////////////////////////////
166void boot_mapping_check() 
167{
[321]168    mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
[258]169
170    // checking mapping availability
171    if (header->signature != IN_MAPPING_SIGNATURE) 
172    {
173        _puts("\n[BOOT ERROR] Illegal mapping signature: ");
174        _putx(header->signature);
175        _puts("\n");
176        _exit();
177    }
[263]178
[258]179    // checking number of clusters
[263]180    if ( (header->x_size  != X_SIZE)  || 
181         (header->y_size  != Y_SIZE)  ||
182         (header->x_width != X_WIDTH) ||
183         (header->y_width != Y_WIDTH) )
[258]184    {
[263]185        _puts("\n[BOOT ERROR] Incoherent X_SIZE or Y_SIZE ");
186        _puts("\n             - In hard_config:  X_SIZE = ");
187        _putd( X_SIZE );
188        _puts(" / Y_SIZE = ");
189        _putd( Y_SIZE );
190        _puts(" / X_WIDTH = ");
191        _putd( X_WIDTH );
192        _puts(" / Y_WIDTH = ");
193        _putd( Y_WIDTH );
194        _puts("\n             - In mapping_info: x_size = ");
195        _putd( header->x_size );
196        _puts(" / y_size = ");
197        _putd( header->y_size );
198        _puts(" / x_width = ");
199        _putd( header->x_width );
200        _puts(" / y_width = ");
201        _putd( header->y_width );
[258]202        _puts("\n");
203        _exit();
204    }
205    // checking number of virtual spaces
206    if (header->vspaces > GIET_NB_VSPACE_MAX) 
207    {
208        _puts("\n[BOOT ERROR] : number of vspaces > GIET_NB_VSPACE_MAX\n");
209        _puts("\n");
210        _exit();
211    }
212
213#if BOOT_DEBUG_MAPPING
[263]214_puts("\n - x_size    = ");
215_putd( header->x_size );
216_puts("\n - y_size    = ");
217_putd( header->y_size );
[258]218_puts("\n - procs     = ");
219_putd( header->procs );
220_puts("\n - periphs   = ");
221_putd( header->periphs );
222_puts("\n - vspaces   = ");
223_putd( header->vspaces );
224_puts("\n - tasks     = ");
225_putd( header->tasks );
226_puts("\n");
227_puts("\n - size of header  = ");
228_putd( MAPPING_HEADER_SIZE );
229_puts("\n - size of cluster = ");
230_putd( MAPPING_CLUSTER_SIZE );
231_puts("\n - size of pseg    = ");
232_putd( MAPPING_PSEG_SIZE );
233_puts("\n - size of proc    = ");
234_putd( MAPPING_PROC_SIZE );
235_puts("\n - size of vspace  = ");
236_putd( MAPPING_VSPACE_SIZE );
237_puts("\n - size of vseg    = ");
238_putd( MAPPING_VSEG_SIZE );
239_puts("\n - size of vobj    = ");
240_putd( MAPPING_VOBJ_SIZE );
241_puts("\n - size of task    = ");
242_putd( MAPPING_TASK_SIZE );
243_puts("\n");
244
[263]245unsigned int cluster_id;
[258]246mapping_cluster_t * cluster = _get_cluster_base(header);
[263]247for( cluster_id = 0; cluster_id < X_SIZE*Y_SIZE ; cluster_id++) 
[258]248{
[263]249    _puts("\n - cluster[");
250    _putd( cluster[cluster_id].x );
251    _puts(",");
252    _putd( cluster[cluster_id].y );
253    _puts("]\n   procs   = ");
254    _putd( cluster[cluster_id].procs );
255    _puts("\n   psegs   = ");
256    _putd( cluster[cluster_id].psegs );
257    _puts("\n   periphs = ");
258    _putd( cluster[cluster_id].periphs );
259    _puts("\n");
[258]260}
261#endif
262
263} // end boot_mapping_check()
264
265//////////////////////////////////////////////////////////////////////////////
[412]266// This function registers a new PTE1 in the page table defined
267// by the vspace_id argument, and the (x,y) coordinates.
268// It updates only the first level PT1.
[258]269//////////////////////////////////////////////////////////////////////////////
[412]270void boot_add_pte1( unsigned int vspace_id,
271                    unsigned int x,
272                    unsigned int y,
273                    unsigned int vpn,        // 20 bits right-justified
274                    unsigned int flags,      // 10 bits left-justified
275                    unsigned int ppn )       // 28 bits right-justified
[258]276{
[427]277
278#if (BOOT_DEBUG_PT > 1)
279_puts(" - PTE1 in PTAB[");
280_putd( vspace_id );
281_puts(",");
282_putd( x );
283_puts(",");
284_putd( y );
285_puts("] : vpn = ");
286_putx( vpn );
287#endif
288
[412]289    // compute index in PT1
290    unsigned int    ix1 = vpn >> 9;         // 11 bits for ix1
[258]291
[412]292    // get page table physical base address
293    paddr_t         pt1_pbase = _ptabs_paddr[vspace_id][x][y];
294
295    // check pt1_base
296    if ( pt1_pbase == 0 )
[258]297    {
[412]298        _puts("\n[BOOT ERROR] in boot_add_pte1() : illegal pbase address for PTAB[");
299        _putd( vspace_id );
300        _puts(",");
301        _putd( x );
302        _puts(",");
303        _putd( y );
304        _puts("]\n");
[258]305        _exit();
306    }
307
[412]308    // compute pte1 : 2 bits V T / 8 bits flags / 3 bits RSVD / 19 bits bppi
309    unsigned int    pte1 = PTE_V |
310                           (flags & 0x3FC00000) |
311                           ((ppn>>9) & 0x0007FFFF);
[258]312
[412]313    // write pte1 in PT1
314    _physical_write( pt1_pbase + 4*ix1, pte1 );
315
316#if (BOOT_DEBUG_PT > 1)
317_puts(" / ppn = ");
318_putx( ppn );
319_puts(" / flags = ");
320_putx( flags );
321_puts("\n");
322#endif
323
324}   // end boot_add_pte1()
325
[258]326//////////////////////////////////////////////////////////////////////////////
[412]327// This function registers a new PTE2 in the page table defined
[347]328// by the vspace_id argument, and the (x,y) coordinates.
[412]329// It updates both the first level PT1 and the second level PT2.
[258]330// As the set of PT2s is implemented as a fixed size array (no dynamic
331// allocation), this function checks a possible overflow of the PT2 array.
332//////////////////////////////////////////////////////////////////////////////
[412]333void boot_add_pte2( unsigned int vspace_id,
334                    unsigned int x,
335                    unsigned int y,
336                    unsigned int vpn,        // 20 bits right-justified
337                    unsigned int flags,      // 10 bits left-justified
338                    unsigned int ppn )       // 28 bits right-justified
[258]339{
[427]340
341#if (BOOT_DEBUG_PT > 1)
342_puts(" - PTE2 in PTAB[");
343_putd( vspace_id );
344_puts(",");
345_putd( x );
346_puts(",");
347_putd( y );
348_puts("] : vpn = ");
349_putx( vpn );
350#endif
351
[258]352    unsigned int ix1;
353    unsigned int ix2;
[347]354    paddr_t      pt2_pbase;     // PT2 physical base address
[412]355    paddr_t      pte2_paddr;    // PTE2 physical address
[258]356    unsigned int pt2_id;        // PT2 index
357    unsigned int ptd;           // PTD : entry in PT1
358
[412]359    ix1 = vpn >> 9;             // 11 bits for ix1
360    ix2 = vpn & 0x1FF;          //  9 bits for ix2
[258]361
[347]362    // get page table physical base address and size
363    paddr_t      pt1_pbase = _ptabs_paddr[vspace_id][x][y];
[258]364
[412]365    // check pt1_base
366    if ( pt1_pbase == 0 )
[258]367    {
[412]368        _puts("\n[BOOT ERROR] in boot_add_pte2() : PTAB[");
369        _putd( vspace_id );
370        _puts(",");
371        _putd( x );
372        _puts(",");
373        _putd( y );
374        _puts("] undefined\n");
[258]375        _exit();
376    }
377
378    // get ptd in PT1
379    ptd = _physical_read(pt1_pbase + 4 * ix1);
380
[347]381    if ((ptd & PTE_V) == 0)    // undefined PTD: compute PT2 base address,
[258]382                               // and set a new PTD in PT1
383    {
[347]384        pt2_id = _ptabs_next_pt2[vspace_id][x][y];
[412]385        if (pt2_id == _ptabs_max_pt2) 
[258]386        {
[412]387            _puts("\n[BOOT ERROR] in boot_add_pte2() : PTAB[");
388            _putd( vspace_id );
389            _puts(",");
390            _putd( x );
391            _puts(",");
392            _putd( y );
393            _puts("] contains not enough PT2s\n");
[258]394            _exit();
395        }
[347]396
397        pt2_pbase = pt1_pbase + PT1_SIZE + PT2_SIZE * pt2_id;
398        ptd = PTE_V | PTE_T | (unsigned int) (pt2_pbase >> 12);
[412]399        _physical_write( pt1_pbase + 4*ix1, ptd);
[347]400        _ptabs_next_pt2[vspace_id][x][y] = pt2_id + 1;
[258]401    }
402    else                       // valid PTD: compute PT2 base address
403    {
404        pt2_pbase = ((paddr_t)(ptd & 0x0FFFFFFF)) << 12;
405    }
406
407    // set PTE in PT2 : flags & PPN in two 32 bits words
[412]408    pte2_paddr  = pt2_pbase + 8 * ix2;
409    _physical_write(pte2_paddr     , (PTE_V |flags) );
410    _physical_write(pte2_paddr + 4 , ppn);
[258]411
[412]412#if (BOOT_DEBUG_PT > 1)
413_puts(" / ppn = ");
414_putx( ppn );
415_puts(" / flags = ");
416_putx( flags );
[347]417_puts("\n");
[258]418#endif
419
[412]420}   // end boot_add_pte2()
[258]421
[412]422////////////////////////////////////////////////////////////////////////////////////
[258]423// Align the value of paddr or vaddr to the required alignement,
424// defined by alignPow2 == L2(alignement).
[412]425////////////////////////////////////////////////////////////////////////////////////
[258]426paddr_t paddr_align_to(paddr_t paddr, unsigned int alignPow2) 
427{
428    paddr_t mask = (1 << alignPow2) - 1;
429    return ((paddr + mask) & ~mask);
430}
431
432unsigned int vaddr_align_to(unsigned int vaddr, unsigned int alignPow2) 
433{
434    unsigned int mask = (1 << alignPow2) - 1;
435    return ((vaddr + mask) & ~mask);
436}
437
[412]438/////////////////////////////////////////////////////////////////////////////////////
439// This function map a vseg identified by the vseg pointer.
440//
441// A given vseg can be mapped in Big Physical Pages (BPP: 2 Mbytes) or in a
442// Small Physical Pages (SPP: 4 Kbytes), depending on the "big" attribute of vseg,
443// with the following rules:
444// - SPP : There is only one vseg in a small physical page, but a single vseg
445//   can cover several contiguous small physical pages.
446// - BPP : It can exist several vsegs in a single big physical page, and a single
447//   vseg can cover several contiguous big physical pages.
448//
449// 1) First step: it computes the vseg length, and register it in vseg->length field.
450//    It computes - for each vobj - the actual vbase address, taking into
451//    account the alignment constraints and register it in vobj->vbase field.
452//
453// 2) Second step: it allocates the required number of physical pages,
454//    computes the physical base address (if the vseg is not identity mapping),
455//    and register it in the vseg pbase field.
456//    Only the 4 vsegs used by the boot code and the peripheral vsegs
457//    can be identity mapping: The first big physical page in cluster[0,0]
458//    is reserved for the 4 boot vsegs.
459//
460// 3) Third step (only for vseg that have the VOBJ_TYPE_PTAB): all page tables
461//    associated to the various vspaces must be packed in the same vseg.
462//    We divide the vseg in M sub-segments, and compute the vbase and pbase
463//    addresses for each page table, and register it in the _ptabs_paddr
464//    and _ptabs_vaddr arrays.
465// 
466/////////////////////////////////////////////////////////////////////////////////////
[427]467void boot_vseg_map( mapping_vseg_t* vseg,
468                    unsigned int    vspace_id )
[258]469{
[412]470    mapping_header_t*   header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
471    mapping_vobj_t*     vobj    = _get_vobj_base(header);
472    mapping_cluster_t*  cluster = _get_cluster_base(header);
473    mapping_pseg_t*     pseg    = _get_pseg_base(header);
[258]474
[412]475    // compute destination cluster pointer & coordinates
476    pseg    = pseg + vseg->psegid;
477    cluster = cluster + pseg->clusterid;
478    unsigned int        x_dest     = cluster->x;
479    unsigned int        y_dest     = cluster->y;
[258]480
[412]481    // compute the first vobj global index
482    unsigned int        vobj_id = vseg->vobj_offset;
483   
484    // compute the "big" vseg attribute
485    unsigned int        big = vseg->big;
[258]486
[412]487    // compute the "is_ram" vseg attribute
488    unsigned int        is_ram;
489    if ( pseg->type == PSEG_TYPE_RAM )  is_ram = 1;
490    else                                is_ram = 0;
[258]491
[412]492    // compute the "is_ptab" attribute
493    unsigned int        is_ptab;
494    if ( vobj[vobj_id].type == VOBJ_TYPE_PTAB ) is_ptab = 1;
495    else                                        is_ptab = 0;
[258]496
[427]497    // compute actual vspace index
498    unsigned int vsid;
499    if ( vspace_id == 0xFFFFFFFF ) vsid = 0;
500    else                           vsid = vspace_id;
501
[412]502    //////////// First step : compute vseg length and vobj(s) vbase
[258]503
[412]504    unsigned int vobj_vbase = vseg->vbase;   // min vbase for first vobj
[258]505
[412]506    for ( vobj_id = vseg->vobj_offset ;
507          vobj_id < (vseg->vobj_offset + vseg->vobjs) ; 
508          vobj_id++ ) 
[258]509    {
[412]510        // compute and register vobj vbase
511        vobj[vobj_id].vbase = vaddr_align_to( vobj_vbase, vobj[vobj_id].align );
512   
513        // compute min vbase for next vobj
514        vobj_vbase = vobj[vobj_id].vbase + vobj[vobj_id].length;
[258]515    }
516
[412]517    // compute and register vseg length (multiple of 4 Kbytes)
518    vseg->length = vaddr_align_to( vobj_vbase - vseg->vbase, 12 );
519   
520    //////////// Second step : compute ppn and npages 
521    //////////// - if identity mapping :  ppn <= vpn
522    //////////// - if vseg is periph   :  ppn <= pseg.base >> 12
523    //////////// - if vseg is ram      :  ppn <= physical memory allocator
[258]524
[412]525    unsigned int ppn;          // first physical page index ( 28 bits = |x|y|bppi|sppi| )
526    unsigned int vpn;          // first virtual page index  ( 20 bits = |ix1|ix2| )
527    unsigned int vpn_max;      // last  virtual page index  ( 20 bits = |ix1|ix2| )
[258]528
[412]529    vpn     = vseg->vbase >> 12;
530    vpn_max = (vseg->vbase + vseg->length - 1) >> 12;
[258]531
[412]532    // compute npages
533    unsigned int npages;       // number of required (big or small) pages
534    if ( big == 0 ) npages  = vpn_max - vpn + 1;            // number of small pages
535    else            npages  = (vpn_max>>9) - (vpn>>9) + 1;  // number of big pages
536
537    // compute ppn
538    if ( vseg->ident )           // identity mapping
[258]539    {
[412]540        ppn = vpn;
[258]541    }
[412]542    else                         // not identity mapping
[258]543    {
[412]544        if ( is_ram )            // RAM : physical memory allocation required
[258]545        {
[412]546            // compute pointer on physical memory allocator in dest cluster
547            pmem_alloc_t*     palloc = &boot_pmem_alloc[x_dest][y_dest];
[258]548
[412]549            if ( big == 0 )             // SPP : small physical pages
550            {
551                // allocate contiguous small physical pages
552                ppn = _get_small_ppn( palloc, npages );
553            }
554            else                            // BPP : big physical pages
555            {
556 
557                // one big page can be shared by several vsegs
558                // we must chek if BPP already allocated
559                if ( is_ptab )   // It cannot be mapped
560                {
561                    ppn = _get_big_ppn( palloc, npages ); 
562                }
563                else             // It can be mapped
564                {
565                    unsigned int ix1   = vpn >> 9;   // 11 bits
[427]566                    paddr_t      paddr = _ptabs_paddr[vsid][x_dest][y_dest] + (ix1<<2);
[412]567                    unsigned int pte1  = _physical_read( paddr );
568                    if ( (pte1 & PTE_V) == 0 )     // BPP not allocated yet
569                    {
570                        // allocate contiguous big physical pages
[433]571                        ppn = _get_big_ppn( palloc, npages );
[412]572                    }
573                    else                           // BPP already allocated
574                    {
[433]575                        // test if new vseg has the same mode bits than
576                        // the other vsegs in the same big page
577                        unsigned int pte1_mode = 0;
578                        if (pte1 & PTE_C) pte1_mode |= C_MODE_MASK;
579                        if (pte1 & PTE_X) pte1_mode |= X_MODE_MASK;
580                        if (pte1 & PTE_W) pte1_mode |= W_MODE_MASK;
581                        if (pte1 & PTE_U) pte1_mode |= U_MODE_MASK;
582                        if (vseg->mode != pte1_mode) {
583                            _puts("\n[BOOT ERROR] in boot_vseg_map() : vseg ");
584                            _puts( vseg->name );
585                            _puts(" has different flags (");
586                            _putx( vseg->mode );
587                            _puts(") than other vsegs sharing the same big page (");
588                            _putx( pte1_mode );
589                            _puts(")");
590                            _exit();
591                        }
592
[412]593                        ppn = ((pte1 << 9) & 0x0FFFFE00);
594                    }
595                }
596                ppn = ppn | (vpn & 0x1FF);
597            }
[258]598        }
[412]599        else                    // PERI : no memory allocation required
[258]600        {
[412]601            ppn = pseg->base >> 12;
[258]602        }
603    }
604
[412]605    // update vseg.pbase field and update vsegs chaining
606    vseg->pbase     = ((paddr_t)ppn) << 12;
607    vseg->next_vseg = pseg->next_vseg;
608    pseg->next_vseg = (unsigned int)vseg;
[258]609
[412]610
611    //////////// Third step : (only if the vseg is a page table)
612    //////////// - compute the physical & virtual base address for each vspace
613    ////////////   by dividing the vseg in several sub-segments.
614    //////////// - register it in _ptabs_vaddr & _ptabs_paddr arrays,
[427]615    ////////////   and initialize next_pt2 allocators.
616    //////////// - reset all entries in first level page tables
[412]617   
618    if ( is_ptab )
[258]619    {
[412]620        unsigned int   vs;        // vspace index
621        unsigned int   nspaces;   // number of vspaces
622        unsigned int   nsp;       // number of small pages for one PTAB
623        unsigned int   offset;    // address offset for current PTAB
[258]624
[412]625        nspaces = header->vspaces;
626        offset  = 0;
[258]627
[412]628        // each PTAB must be aligned on a 8 Kbytes boundary
[427]629        nsp = ( vseg->length >> 12 ) / nspaces;
[412]630        if ( (nsp & 0x1) == 0x1 ) nsp = nsp - 1;
[258]631
[412]632        // compute max_pt2
633        _ptabs_max_pt2 = ((nsp<<12) - PT1_SIZE) / PT2_SIZE;
[433]634
[412]635        for ( vs = 0 ; vs < nspaces ; vs++ )
[258]636        {
[433]637            _ptabs_vaddr   [vs][x_dest][y_dest] = (vpn + offset) << 12;
[412]638            _ptabs_paddr   [vs][x_dest][y_dest] = ((paddr_t)(ppn + offset)) << 12;
639            _ptabs_next_pt2[vs][x_dest][y_dest] = 0;
[427]640            offset += nsp;
[433]641
[427]642            // reset all entries in PT1 (8 Kbytes)
643            _physical_memset( _ptabs_paddr[vs][x_dest][y_dest], PT1_SIZE, 0 );
[258]644        }
645    }
646
[412]647#if BOOT_DEBUG_PT
648_puts("[BOOT DEBUG] ");
[433]649_puts( vseg->name );
[412]650_puts(" in cluster[");
651_putd( x_dest );
652_puts(",");
653_putd( y_dest );
654_puts("] : vbase = ");
655_putx( vseg->vbase );
656_puts(" / length = ");
657_putx( vseg->length );
658if ( big ) _puts(" / BIG   / npages = ");
659else       _puts(" / SMALL / npages = ");
660_putd( npages );
661_puts(" / pbase = ");
662_putl( vseg->pbase );
663_puts("\n");
664#endif
665
666} // end boot_vseg_map()
667
668/////////////////////////////////////////////////////////////////////////////////////
669// For the vseg defined by the vseg pointer, this function register all PTEs
670// in one or several page tables.
[436]671// It is a global vseg (kernel vseg) if (vspace_id == 0xFFFFFFFF).
[412]672// The number of involved PTABs depends on the "local" and "global" attributes:
673//  - PTEs are replicated in all vspaces for a global vseg.
674//  - PTEs are replicated in all clusters for a non local vseg.
675/////////////////////////////////////////////////////////////////////////////////////
[427]676void boot_vseg_pte( mapping_vseg_t*  vseg,
677                    unsigned int     vspace_id )
[412]678{
679    // compute the "global" vseg attribute and actual vspace index
680    unsigned int        global;
681    unsigned int        vsid;   
682    if ( vspace_id == 0xFFFFFFFF )
[258]683    {
[412]684        global = 1;
685        vsid   = 0;
[258]686    }
[412]687    else
[258]688    {
[412]689        global = 0;
690        vsid   = vspace_id;
[258]691    }
692
[412]693    // compute the "local" and "big" attributes
694    unsigned int        local  = vseg->local;
695    unsigned int        big    = vseg->big;
[258]696
[412]697    // compute vseg flags
698    // The three flags (Local, Remote and Dirty) are set to 1 to reduce
699    // latency of TLB miss (L/R) and write (D): Avoid hardware update
700    // mechanism for these flags because GIET_VM does use these flags.
701    unsigned int flags = 0;
702    if (vseg->mode & C_MODE_MASK) flags |= PTE_C;
703    if (vseg->mode & X_MODE_MASK) flags |= PTE_X;
704    if (vseg->mode & W_MODE_MASK) flags |= PTE_W;
705    if (vseg->mode & U_MODE_MASK) flags |= PTE_U;
706    if ( global )                 flags |= PTE_G;
707                                  flags |= PTE_L;
708                                  flags |= PTE_R;
709                                  flags |= PTE_D;
[258]710
[412]711    // compute VPN, PPN and number of pages (big or small)
712    unsigned int vpn     = vseg->vbase >> 12;
713    unsigned int vpn_max = (vseg->vbase + vseg->length - 1) >> 12;
714    unsigned int ppn     = (unsigned int)(vseg->pbase >> 12);
715    unsigned int npages;
716    if ( big == 0 ) npages  = vpn_max - vpn + 1;           
717    else            npages  = (vpn_max>>9) - (vpn>>9) + 1; 
718
719    // compute destination cluster coordinates
720    unsigned int        x_dest;
721    unsigned int        y_dest;
722    mapping_header_t*   header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
723    mapping_cluster_t*  cluster = _get_cluster_base(header);
724    mapping_pseg_t*     pseg    = _get_pseg_base(header);
725    pseg     = pseg + vseg->psegid;
726    cluster  = cluster + pseg->clusterid;
727    x_dest   = cluster->x;
728    y_dest   = cluster->y;
729
730    unsigned int p;     // iterator for physical page index
731    unsigned int x;     // iterator for cluster x coordinate 
732    unsigned int y;     // iterator for cluster y coordinate 
733    unsigned int v;     // iterator for vspace index
734
735    // loop on PTEs
736    for ( p = 0 ; p < npages ; p++ )
737    { 
738        if  ( (local != 0) && (global == 0) )         // one cluster  / one vspace
[258]739        {
[412]740            if ( big )   // big pages => PTE1s
741            {
742                boot_add_pte1( vsid,
743                               x_dest,
744                               y_dest,
745                               vpn + (p<<9),
746                               flags, 
747                               ppn + (p<<9) );
748            }
749            else         // small pages => PTE2s
750            {
751                boot_add_pte2( vsid,
752                               x_dest,
753                               y_dest,
754                               vpn + p,     
755                               flags, 
756                               ppn + p );
757            }
[258]758        }
[412]759        else if ( (local == 0) && (global == 0) )     // all clusters / one vspace
[258]760        {
[412]761            for ( x = 0 ; x < X_SIZE ; x++ )
[258]762            {
[412]763                for ( y = 0 ; y < Y_SIZE ; y++ )
764                {
765                    if ( big )   // big pages => PTE1s
766                    {
767                        boot_add_pte1( vsid,
768                                       x,
769                                       y,
770                                       vpn + (p<<9),
771                                       flags, 
772                                       ppn + (p<<9) );
773                    }
774                    else         // small pages => PTE2s
775                    {
776                        boot_add_pte2( vsid,
777                                       x,
778                                       y,
779                                       vpn + p,
780                                       flags, 
781                                       ppn + p );
782                    }
783                }
[258]784            }
[412]785        }
786        else if ( (local != 0) && (global != 0) )     // one cluster  / all vspaces
787        {
788            for ( v = 0 ; v < header->vspaces ; v++ )
[258]789            {
[412]790                if ( big )   // big pages => PTE1s
791                {
792                    boot_add_pte1( v,
793                                   x_dest,
794                                   y_dest,
795                                   vpn + (p<<9),
796                                   flags, 
797                                   ppn + (p<<9) );
798                }
799                else         // small pages = PTE2s
800                { 
801                    boot_add_pte2( v,
802                                   x_dest,
803                                   y_dest,
804                                   vpn + p,
805                                   flags, 
806                                   ppn + p );
807                }
[258]808            }
[412]809        }
810        else if ( (local == 0) && (global != 0) )     // all clusters / all vspaces
811        {
812            for ( x = 0 ; x < X_SIZE ; x++ )
[258]813            {
[412]814                for ( y = 0 ; y < Y_SIZE ; y++ )
815                {
816                    for ( v = 0 ; v < header->vspaces ; v++ )
817                    {
818                        if ( big )  // big pages => PTE1s
819                        {
820                            boot_add_pte1( v,
821                                           x,
822                                           y,
823                                           vpn + (p<<9),
824                                           flags, 
825                                           ppn + (p<<9) );
826                        }
827                        else        // small pages -> PTE2s
828                        {
829                            boot_add_pte2( v,
830                                           x,
831                                           y,
832                                           vpn + p,
833                                           flags, 
834                                           ppn + p );
835                        }
836                    }
837                }
[258]838            }
839        }
[412]840    }  // end for pages
[427]841}  // end boot_vseg_pte()
[258]842
[412]843///////////////////////////////////////////////////////////////////////////////
844// This function initialises the page tables for all vspaces defined
845// in the mapping_info data structure.
846// For each vspace, there is one page table per cluster.
847// In each cluster all page tables for the different vspaces must be
848// packed in one vseg occupying one single BPP (Big Physical Page).
[258]849//
[412]850// For each vseg, the mapping is done in two steps:
[436]851// 1) mapping : the boot_vseg_map() function allocates contiguous BPPs
[412]852//    or SPPs (if the vseg is not associated to a peripheral), and register
853//    the physical base address in the vseg pbase field. It initialises the
854//    _ptabs_vaddr and _ptabs_paddr arrays if the vseg is a PTAB.
855//
[436]856// 2) page table initialisation : the boot_vseg_pte() function initialise
[412]857//    the PTEs (both PTE1 and PTE2) in one or several page tables:
858//    - PTEs are replicated in all vspaces for a global vseg.
859//    - PTEs are replicated in all clusters for a non local vseg.
860//
861// We must handle vsegs in the following order
862//   1) all global vsegs containing a page table,
863//   2) all global vsegs occupying more than one BPP,
864//   3) all others global vsegs
865//   4) all private vsegs in user space.
866///////////////////////////////////////////////////////////////////////////////
[436]867void boot_ptabs_init() 
[258]868{
[412]869    mapping_header_t*   header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
870    mapping_vspace_t*   vspace = _get_vspace_base(header);
871    mapping_vseg_t*     vseg   = _get_vseg_base(header);
872    mapping_vobj_t*     vobj   = _get_vobj_base(header);
[258]873
874    unsigned int vspace_id;
875    unsigned int vseg_id;
876
877    if (header->vspaces == 0 )
878    {
[436]879        _puts("\n[BOOT ERROR] in boot_ptabs_init() : mapping ");
[258]880        _puts( header->name );
881        _puts(" contains no vspace\n");
882        _exit();
883    }
884
[412]885    ///////// Phase 1 : global vsegs containing a PTAB (two loops required)
886
[258]887#if BOOT_DEBUG_PT
[412]888_puts("\n[BOOT DEBUG] map PTAB global vsegs\n");
[258]889#endif
890
[412]891    for (vseg_id = 0; vseg_id < header->globals; vseg_id++) 
892    {
893        unsigned int vobj_id = vseg[vseg_id].vobj_offset;
894        if ( (vobj[vobj_id].type == VOBJ_TYPE_PTAB) )
895        {
[427]896            boot_vseg_map( &vseg[vseg_id], 0xFFFFFFFF );
[412]897            vseg[vseg_id].mapped = 1;
898        }
899    }
[258]900
901    for (vseg_id = 0; vseg_id < header->globals; vseg_id++) 
902    {
[412]903        unsigned int vobj_id = vseg[vseg_id].vobj_offset;
904        if ( (vobj[vobj_id].type == VOBJ_TYPE_PTAB) )
905        {
[427]906            boot_vseg_pte( &vseg[vseg_id], 0xFFFFFFFF );
[412]907            vseg[vseg_id].mapped = 1;
908        }
[258]909    }
910
[412]911    ///////// Phase 2 : global vsegs occupying more than one BPP (one loop)
912
913#if BOOT_DEBUG_PT
914_puts("\n[BOOT DEBUG] map all multi-BPP global vsegs\n");
915#endif
916
[258]917    for (vseg_id = 0; vseg_id < header->globals; vseg_id++) 
918    {
[412]919        unsigned int vobj_id = vseg[vseg_id].vobj_offset;
920        if ( (vobj[vobj_id].length > 0x200000) &&
921             (vseg[vseg_id].mapped == 0) )
922        {
[427]923            boot_vseg_map( &vseg[vseg_id], 0xFFFFFFFF );
[412]924            vseg[vseg_id].mapped = 1;
[427]925            boot_vseg_pte( &vseg[vseg_id], 0xFFFFFFFF );
[412]926        }
[258]927    }
928
[412]929    ///////// Phase 3 : all others global vsegs (one loop)
[347]930
[412]931#if BOOT_DEBUG_PT
932_puts("\n[BOOT DEBUG] map all others global vsegs\n");
933#endif
934
935    for (vseg_id = 0; vseg_id < header->globals; vseg_id++) 
936    {
937        if ( vseg[vseg_id].mapped == 0 )
938        {
[427]939            boot_vseg_map( &vseg[vseg_id], 0xFFFFFFFF );
[412]940            vseg[vseg_id].mapped = 1;
[427]941            boot_vseg_pte( &vseg[vseg_id], 0xFFFFFFFF );
[412]942        }
943    }
944
945    ///////// Phase 4 : all private vsegs (two nested loops)
946
[258]947    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
948    {
949
950#if BOOT_DEBUG_PT
[412]951_puts("\n[BOOT DEBUG] map private vsegs for vspace ");
952_puts( vspace[vspace_id].name );
953_puts("\n");
[258]954#endif
955
956        for (vseg_id = vspace[vspace_id].vseg_offset;
957             vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs);
958             vseg_id++) 
959        {
[427]960            boot_vseg_map( &vseg[vseg_id], vspace_id );
[412]961            vseg[vseg_id].mapped = 1;
[427]962            boot_vseg_pte( &vseg[vseg_id], vspace_id );
[258]963        }
964    }
965
[412]966#if (BOOT_DEBUG_PT > 1)
[309]967mapping_vseg_t*    curr;
968mapping_pseg_t*    pseg    = _get_pseg_base(header);
969mapping_cluster_t* cluster = _get_cluster_base(header);
970unsigned int       pseg_id;
[258]971for( pseg_id = 0 ; pseg_id < header->psegs ; pseg_id++ )
972{
[309]973    unsigned int cluster_id = pseg[pseg_id].clusterid;
[412]974    _puts("\n[BOOT DEBUG] vsegs mapped on pseg ");
[258]975    _puts( pseg[pseg_id].name );
[309]976    _puts(" in cluster[");
977    _putd( cluster[cluster_id].x );
978    _puts(",");
979    _putd( cluster[cluster_id].y );
[412]980    _puts("]\n");
[258]981    for( curr = (mapping_vseg_t*)pseg[pseg_id].next_vseg ;
982         curr != 0 ;
983         curr = (mapping_vseg_t*)curr->next_vseg )
984    {
985        _puts(" - vseg ");
986        _puts( curr->name );
987        _puts(" : len = ");
988        _putx( curr->length );
989        _puts(" / vbase ");
[295]990        _putx( curr->vbase );
[258]991        _puts(" / pbase ");
992        _putl( curr->pbase );
993        _puts("\n");
994    } 
995}
996#endif
997
[412]998} // end boot_ptabs_init()
[258]999
1000///////////////////////////////////////////////////////////////////////////////
[452]1001// This function initializes the private vobjs that have the CONST type.
[258]1002// The MMU is supposed to be activated...
1003///////////////////////////////////////////////////////////////////////////////
1004void boot_vobjs_init() 
1005{
[321]1006    mapping_header_t* header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
[258]1007    mapping_vspace_t* vspace = _get_vspace_base(header);
1008    mapping_vobj_t* vobj     = _get_vobj_base(header);
1009
1010    unsigned int vspace_id;
1011    unsigned int vobj_id;
1012
1013    // loop on the vspaces
1014    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
1015    {
1016
1017#if BOOT_DEBUG_VOBJS
1018_puts("\n[BOOT DEBUG] ****** vobjs initialisation in vspace ");
1019_puts(vspace[vspace_id].name);
1020_puts(" ******\n");
1021#endif
1022
[347]1023        _set_mmu_ptpr( (unsigned int)(_ptabs_paddr[vspace_id][0][0] >> 13) );
[258]1024
1025        // loop on the vobjs
1026        for (vobj_id = vspace[vspace_id].vobj_offset;
1027             vobj_id < (vspace[vspace_id].vobj_offset + vspace[vspace_id].vobjs);
1028             vobj_id++) 
1029        {
[452]1030            if ( (vobj[vobj_id].type) == VOBJ_TYPE_CONST )
[258]1031            {
[309]1032#if BOOT_DEBUG_VOBJS
[258]1033_puts("CONST   : ");
1034_puts(vobj[vobj_id].name);
[452]1035_puts(" / vaddr  = ");
[309]1036_putx(vobj[vobj_id].vaddr);
[452]1037_puts(" / paddr  = ");
[258]1038_putl(vobj[vobj_id].paddr);
[452]1039_puts(" / value  = ");
[309]1040_putx(vobj[vobj_id].init);
1041_puts("\n");
1042#endif
[452]1043                unsigned int* addr = (unsigned int *) vobj[vobj_id].vbase;
1044                *addr = vobj[vobj_id].init;
1045            }
1046        }
1047    }
[258]1048} // end boot_vobjs_init()
1049
1050///////////////////////////////////////////////////////////////////////////////
1051// This function returns in the vbase and length buffers the virtual base
1052// address and the length of the  segment allocated to the schedulers array
1053// in the cluster defined by the clusterid argument.
1054///////////////////////////////////////////////////////////////////////////////
1055void boot_get_sched_vaddr( unsigned int  cluster_id,
1056                           unsigned int* vbase, 
1057                           unsigned int* length )
1058{
[321]1059    mapping_header_t* header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
[258]1060    mapping_vobj_t*   vobj   = _get_vobj_base(header);
1061    mapping_vseg_t*   vseg   = _get_vseg_base(header);
1062    mapping_pseg_t*   pseg   = _get_pseg_base(header);
1063
1064    unsigned int vseg_id;
1065    unsigned int found = 0;
1066
1067    for ( vseg_id = 0 ; (vseg_id < header->vsegs) && (found == 0) ; vseg_id++ )
1068    {
1069        if ( (vobj[vseg[vseg_id].vobj_offset].type == VOBJ_TYPE_SCHED) && 
[263]1070             (pseg[vseg[vseg_id].psegid].clusterid == cluster_id ) )
[258]1071        {
1072            *vbase  = vseg[vseg_id].vbase;
1073            *length = vobj[vseg[vseg_id].vobj_offset].length;
1074            found = 1;
1075        }
1076    }
1077    if ( found == 0 )
1078    {
[263]1079        mapping_cluster_t* cluster = _get_cluster_base(header);
1080        _puts("\n[BOOT ERROR] No vobj of type SCHED in cluster [");
1081        _putd( cluster[cluster_id].x );
1082        _puts(",");
1083        _putd( cluster[cluster_id].y );
1084        _puts("]\n");
[258]1085        _exit();
1086    }
1087} // end boot_get_sched_vaddr()
1088
1089////////////////////////////////////////////////////////////////////////////////////
1090// This function initialises all processors schedulers.
1091// This is done by processor 0, and the MMU must be activated.
[412]1092// - In Step 1, it initialises the _schedulers[x][y][l] pointers array, and scan
1093//              the processors for a first initialisation of the schedulers:
1094//              idle_task context, and HWI / SWI / PTI vectors.
[321]1095// - In Step 2, it scan all tasks in all vspaces to complete the tasks contexts,
1096//              initialisation as specified in the mapping_info data structure.
[258]1097////////////////////////////////////////////////////////////////////////////////////
1098void boot_schedulers_init() 
1099{
[321]1100    mapping_header_t*  header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
[258]1101    mapping_cluster_t* cluster = _get_cluster_base(header);
1102    mapping_vspace_t*  vspace  = _get_vspace_base(header);
1103    mapping_task_t*    task    = _get_task_base(header);
1104    mapping_vobj_t*    vobj    = _get_vobj_base(header);
[295]1105    mapping_periph_t*  periph  = _get_periph_base(header);
[258]1106    mapping_irq_t*     irq     = _get_irq_base(header);
1107
1108    unsigned int cluster_id;    // cluster index in mapping_info
[295]1109    unsigned int periph_id;     // peripheral index in mapping_info
[258]1110    unsigned int irq_id;        // irq index in mapping_info
1111    unsigned int vspace_id;     // vspace index in mapping_info
1112    unsigned int task_id;       // task index in mapping_info
[321]1113    unsigned int vobj_id;       // vobj index in mapping_info
[258]1114
[321]1115    unsigned int lpid;          // local processor index (for several loops)
1116
[436]1117    // WTI allocators to processors (for HWIs translated to WTIs) 
1118    // In all clusters the first NB_PROCS_MAX WTIs are reserved for WAKUP
[321]1119    unsigned int alloc_wti_channel[X_SIZE*Y_SIZE];   // one per cluster
[258]1120
[321]1121    // pointers on the XCU and PIC peripherals
1122    mapping_periph_t*  xcu = NULL;
1123    mapping_periph_t*  pic = NULL;
1124
[412]1125    unsigned int          sched_vbase;  // schedulers array vbase address in a cluster
1126    unsigned int          sched_length; // schedulers array length
1127    static_scheduler_t*   psched;       // pointer on processor scheduler
[321]1128
[258]1129    /////////////////////////////////////////////////////////////////////////
1130    // Step 1 : loop on the clusters and on the processors
1131    //          to initialize the schedulers[] array of pointers,
[412]1132    //          idle task context and interrupt vectors.
[258]1133    // Implementation note:
[347]1134    // We need to use both (proc_id) to scan the mapping info structure,
1135    // and (x,y,lpid) to access the schedulers array.
[258]1136
[263]1137    for (cluster_id = 0 ; cluster_id < X_SIZE*Y_SIZE ; cluster_id++) 
[258]1138    {
[263]1139        unsigned int x          = cluster[cluster_id].x;
1140        unsigned int y          = cluster[cluster_id].y;
[258]1141
1142#if BOOT_DEBUG_SCHED
[263]1143_puts("\n[BOOT DEBUG] Initialise schedulers in cluster[");
1144_putd( x );
1145_puts(",");
1146_putd( y );
1147_puts("]\n");
[258]1148#endif
[321]1149        alloc_wti_channel[cluster_id] = NB_PROCS_MAX;
[258]1150
1151        // checking processors number
[295]1152        if ( cluster[cluster_id].procs > NB_PROCS_MAX )
[258]1153        {
[263]1154            _puts("\n[BOOT ERROR] Too much processors in cluster[");
1155            _putd( x );
1156            _puts(",");
1157            _putd( y );
1158            _puts("]\n");
[258]1159            _exit();
1160        }
1161 
[295]1162        // no schedulers initialisation if nprocs == 0
1163        if ( cluster[cluster_id].procs > 0 )
[258]1164        {
[412]1165            // get scheduler array virtual base address in cluster[cluster_id]
[295]1166            boot_get_sched_vaddr( cluster_id, &sched_vbase, &sched_length );
[258]1167
[412]1168            if ( sched_length < (cluster[cluster_id].procs<<13) ) // 8 Kbytes per scheduler
[295]1169            {
1170                _puts("\n[BOOT ERROR] Schedulers segment too small in cluster[");
1171                _putd( x );
1172                _puts(",");
1173                _putd( y );
1174                _puts("]\n");
1175                _exit();
1176            }
[263]1177
[436]1178            // scan peripherals to find the XCU and the PIC component
[321]1179
1180            xcu = NULL; 
[295]1181            for ( periph_id = cluster[cluster_id].periph_offset ;
1182                  periph_id < cluster[cluster_id].periph_offset + cluster[cluster_id].periphs;
1183                  periph_id++ )
1184            {
[436]1185                if( periph[periph_id].type == PERIPH_TYPE_XCU ) 
[295]1186                {
[321]1187                    xcu = &periph[periph_id];
1188
1189                    if ( xcu->arg < cluster[cluster_id].procs )
1190                    {
1191                        _puts("\n[BOOT ERROR] Not enough inputs for XCU[");
1192                        _putd( x );
1193                        _puts(",");
1194                        _putd( y );
1195                        _puts("]\n");
1196                        _exit();
1197                    }
[295]1198                }
[321]1199                if( periph[periph_id].type == PERIPH_TYPE_PIC )   
1200                {
1201                    pic = &periph[periph_id];
1202                }
[295]1203            } 
[321]1204            if ( xcu == NULL )
[295]1205            {         
[436]1206                _puts("\n[BOOT ERROR] No XCU component in cluster[");
[295]1207                _putd( x );
1208                _puts(",");
1209                _putd( y );
1210                _puts("]\n");
1211                _exit();
1212            }
1213
[412]1214            // loop on processors for schedulers default values
[321]1215            // initialisation, including WTI and PTI vectors
[295]1216            for ( lpid = 0 ; lpid < cluster[cluster_id].procs ; lpid++ )
1217            {
[412]1218                // pointer on processor scheduler
1219                psched = (static_scheduler_t*)(sched_vbase + (lpid<<13));
[295]1220
[412]1221                // initialise the schedulers pointers array
1222                _schedulers[x][y][lpid] = psched;
1223
[258]1224#if BOOT_DEBUG_SCHED
[412]1225unsigned int   sched_vbase = (unsigned int)_schedulers[x][y][lpid];
1226unsigned int   sched_ppn;
1227unsigned int   sched_flags;
1228paddr_t        sched_pbase;
1229
1230page_table_t* ptab = (page_table_t*)(_ptabs_vaddr[0][x][y]);
1231_v2p_translate( ptab, sched_vbase>>12, &sched_ppn, &sched_flags );
1232sched_pbase = ((paddr_t)sched_ppn)<<12;
1233
[295]1234_puts("\nProc[");
[263]1235_putd( x );
[295]1236_puts(",");
[263]1237_putd( y );
[295]1238_puts(",");
[263]1239_putd( lpid );
[412]1240_puts("] : scheduler vbase = ");
1241_putx( sched_vbase );
1242_puts(" : scheduler pbase = ");
1243_putl( sched_pbase );
[258]1244_puts("\n");
1245#endif
[295]1246                // initialise the "tasks" and "current" variables default values
[412]1247                psched->tasks   = 0;
1248                psched->current = IDLE_TASK_INDEX;
[258]1249
[321]1250                // default values for HWI / PTI / SWI vectors (valid bit = 0)
[295]1251                unsigned int slot;
1252                for (slot = 0; slot < 32; slot++)
1253                {
[412]1254                    psched->hwi_vector[slot] = 0;
1255                    psched->pti_vector[slot] = 0;
1256                    psched->wti_vector[slot] = 0;
[295]1257                }
[258]1258
[321]1259                // WTI[lpid] <= ISR_WAKUP / PTI[lpid] <= ISR_TICK
[412]1260                psched->wti_vector[lpid] = ISR_WAKUP | 0x80000000;
1261                psched->pti_vector[lpid] = ISR_TICK  | 0x80000000;
[321]1262
[295]1263                // initializes the idle_task context in scheduler:
1264                // - the SR slot is 0xFF03 because this task run in kernel mode.
1265                // - it uses the page table of vspace[0]
1266                // - it uses the kernel TTY terminal
[392]1267                // - slots containing addresses (SP, RA, EPC)
1268                //   must be initialised by kernel_init()
[258]1269
[412]1270                psched->context[IDLE_TASK_INDEX][CTX_CR_ID]   = 0;
1271                psched->context[IDLE_TASK_INDEX][CTX_SR_ID]   = 0xFF03;
1272                psched->context[IDLE_TASK_INDEX][CTX_PTPR_ID] = _ptabs_paddr[0][x][y]>>13;
1273                psched->context[IDLE_TASK_INDEX][CTX_PTAB_ID] = _ptabs_vaddr[0][x][y];
1274                psched->context[IDLE_TASK_INDEX][CTX_TTY_ID]  = 0;
1275                psched->context[IDLE_TASK_INDEX][CTX_LTID_ID] = IDLE_TASK_INDEX;
1276                psched->context[IDLE_TASK_INDEX][CTX_VSID_ID] = 0;
1277                psched->context[IDLE_TASK_INDEX][CTX_RUN_ID]  = 1;
1278
[321]1279            }  // end for processors
[258]1280
[321]1281            // scan HWIs connected to local XCU
1282            // for round-robin allocation to processors
1283            lpid = 0;
1284            for ( irq_id = xcu->irq_offset ;
1285                  irq_id < xcu->irq_offset + xcu->irqs ;
[295]1286                  irq_id++ )
[258]1287            {
[321]1288                unsigned int type    = irq[irq_id].srctype;
1289                unsigned int srcid   = irq[irq_id].srcid;
1290                unsigned int isr     = irq[irq_id].isr & 0xFFFF;
1291                unsigned int channel = irq[irq_id].channel << 16;
1292
1293                if ( (type != IRQ_TYPE_HWI) || (srcid > 31) )
[295]1294                {
[321]1295                    _puts("\n[BOOT ERROR] Bad IRQ in XCU of cluster[");
[295]1296                    _putd( x );
1297                    _puts(",");
1298                    _putd( y );
1299                    _puts("]\n");
1300                    _exit();
1301                }
[258]1302
[412]1303                _schedulers[x][y][lpid]->hwi_vector[srcid] = isr | channel | 0x80000000;
[321]1304                lpid = (lpid + 1) % cluster[cluster_id].procs; 
[258]1305
[321]1306            } // end for irqs
1307        } // end if nprocs > 0
1308    } // end for clusters
[258]1309
[321]1310    // If there is an external PIC component, we scan HWIs connected to PIC
1311    // for Round Robin allocation (as WTI) to processors.
1312    // We allocate one WTI per processor, starting from proc[0,0,0],
1313    // and we increment (cluster_id, lpid) as required.
1314    if ( pic != NULL )
1315    {   
1316        unsigned int cluster_id = 0;   // index in clusters array
1317        unsigned int lpid       = 0;   // processor local index
1318
1319        // scan IRQS defined in PIC
1320        for ( irq_id = pic->irq_offset ;
1321              irq_id < pic->irq_offset + pic->irqs ;
1322              irq_id++ )
1323        {
1324            // compute next values for (cluster_id,lpid)
1325            // if no more procesor available in current cluster
1326            unsigned int overflow = 0;
1327            while ( (lpid >= cluster[cluster_id].procs) ||
1328                    (alloc_wti_channel[cluster_id] >= xcu->arg) )
1329            {
1330                overflow++;
1331                cluster_id = (cluster_id + 1) % (X_SIZE*Y_SIZE);
1332                lpid       = 0;
1333
1334                // overflow detection
1335                if ( overflow > (X_SIZE*Y_SIZE*NB_PROCS_MAX*32) )
1336                {
1337                    _puts("\n[BOOT ERROR] Not enough processors for external IRQs\n");
1338                    _exit();
1339                }
1340            }
1341
1342            unsigned int type    = irq[irq_id].srctype;
1343            unsigned int srcid   = irq[irq_id].srcid;
1344            unsigned int isr     = irq[irq_id].isr & 0xFFFF;
1345            unsigned int channel = irq[irq_id].channel << 16;
1346
1347            if ( (type != IRQ_TYPE_HWI) || (srcid > 31) )
1348            {
1349                _puts("\n[BOOT ERROR] Bad IRQ in PIC component\n");
1350                _exit();
1351            }
1352
1353            // get scheduler[cluster_id] address
1354            unsigned int x          = cluster[cluster_id].x;
1355            unsigned int y          = cluster[cluster_id].y;
1356            unsigned int cluster_xy = (x<<Y_WIDTH) + y;
[412]1357            psched                  = _schedulers[x][y][lpid];
[321]1358
1359            // update WTI vector for scheduler[cluster_id][lpid]
[412]1360            unsigned int index            = alloc_wti_channel[cluster_id];
1361            psched->wti_vector[index]     = isr | channel | 0x80000000;
[321]1362            alloc_wti_channel[cluster_id] = index + 1;
[412]1363            lpid                          = lpid + 1;
[321]1364
1365            // update IRQ fields in mapping for PIC initialisation
1366            irq[irq_id].dest_id = index;
1367            irq[irq_id].dest_xy = cluster_xy;
1368
1369        }  // end for IRQs
1370    } // end if PIC
1371               
[258]1372#if BOOT_DEBUG_SCHED
[321]1373for ( cluster_id = 0 ; cluster_id < (X_SIZE*Y_SIZE) ; cluster_id++ )
1374{
1375    unsigned int x          = cluster[cluster_id].x;
1376    unsigned int y          = cluster[cluster_id].y;
1377    unsigned int slot;
1378    unsigned int entry;
1379    for ( lpid = 0 ; lpid < cluster[cluster_id].procs ; lpid++ )
1380    {
[412]1381        psched = _schedulers[x][y][lpid];
1382       
[321]1383        _puts("\n*** IRQS for proc[");
1384        _putd( x );
1385        _puts(",");
1386        _putd( y );
[329]1387        _puts(",");
[321]1388        _putd( lpid );
1389        _puts("]\n");
1390        for ( slot = 0 ; slot < 32 ; slot++ )
1391        {
[412]1392            entry = psched->hwi_vector[slot];
[321]1393            if ( entry & 0x80000000 ) 
1394            {
1395                _puts(" - HWI ");
1396                _putd( slot );
1397                _puts(" / isrtype = ");
1398                _putd( entry & 0xFFFF ); 
1399                _puts(" / channel = ");
1400                _putd( (entry >> 16) & 0x7FFF ); 
1401                _puts("\n");
1402            }
1403        }
1404        for ( slot = 0 ; slot < 32 ; slot++ )
1405        {
[412]1406            entry = psched->wti_vector[slot];
[321]1407            if ( entry & 0x80000000 ) 
1408            {
1409                _puts(" - WTI ");
1410                _putd( slot );
1411                _puts(" / isrtype = ");
1412                _putd( entry & 0xFFFF ); 
1413                _puts(" / channel = ");
1414                _putd( (entry >> 16) & 0x7FFF ); 
1415                _puts("\n");
1416            }
1417        }
1418        for ( slot = 0 ; slot < 32 ; slot++ )
1419        {
[412]1420            entry = psched->pti_vector[slot];
[321]1421            if ( entry & 0x80000000 ) 
1422            {
1423                _puts(" - PTI ");
1424                _putd( slot );
1425                _puts(" / isrtype = ");
1426                _putd( entry & 0xFFFF ); 
1427                _puts(" / channel = ");
1428                _putd( (entry >> 16) & 0x7FFF ); 
1429                _puts("\n");
1430            }
1431        }
1432    }
1433}
[258]1434#endif
1435
1436    ///////////////////////////////////////////////////////////////////
[295]1437    // Step 2 : loop on the vspaces and the tasks  to complete
1438    //          the schedulers and task contexts initialisation.
[258]1439
1440    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
1441    {
1442        // We must set the PTPR depending on the vspace, because the start_vector
1443        // and the stack address are defined in virtual space.
[347]1444        _set_mmu_ptpr( (unsigned int)(_ptabs_paddr[vspace_id][0][0] >> 13) );
[258]1445
[412]1446        // loop on the tasks in vspace (task_id is the global index in mapping)
[258]1447        for (task_id = vspace[vspace_id].task_offset;
1448             task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks);
1449             task_id++) 
1450        {
[295]1451            // compute the cluster coordinates & local processor index
[263]1452            unsigned int x          = cluster[task[task_id].clusterid].x;
1453            unsigned int y          = cluster[task[task_id].clusterid].y;
1454            unsigned int cluster_xy = (x<<Y_WIDTH) + y;
[295]1455            unsigned int lpid       = task[task_id].proclocid;                 
[263]1456
[258]1457#if BOOT_DEBUG_SCHED
1458_puts("\n[BOOT DEBUG] Initialise context for task ");
1459_puts( task[task_id].name );
1460_puts(" in vspace ");
1461_puts( vspace[vspace_id].name );
[309]1462_puts("\n");
[258]1463#endif
1464            // compute gpid (global processor index) and scheduler base address
[427]1465            unsigned int gpid = (cluster_xy << P_WIDTH) + lpid;
[347]1466            psched            = _schedulers[x][y][lpid];
[258]1467
1468            // ctx_sr : value required before an eret instruction
1469            unsigned int ctx_sr = 0x0000FF13;
1470
1471            // ctx_ptpr : page table physical base address (shifted by 13 bit)
[347]1472            unsigned int ctx_ptpr = (unsigned int)(_ptabs_paddr[vspace_id][x][y] >> 13);
[258]1473
1474            // ctx_ptab : page_table virtual base address
[412]1475            unsigned int ctx_ptab = _ptabs_vaddr[vspace_id][x][y];
[258]1476
1477            // ctx_epc : Get the virtual address of the memory location containing
1478            // the task entry point : the start_vector is stored by GCC in the seg_data
1479            // segment and we must wait the .elf loading to get the entry point value...
[321]1480            vobj_id = vspace[vspace_id].start_vobj_id;     
[412]1481            unsigned int ctx_epc = vobj[vobj_id].vbase + (task[task_id].startid)*4;
[258]1482
1483            // ctx_sp :  Get the vobj containing the stack
[321]1484            vobj_id = task[task_id].stack_vobj_id;
[412]1485            unsigned int ctx_sp = vobj[vobj_id].vbase + vobj[vobj_id].length;
[258]1486
1487            // get local task index in scheduler
1488            unsigned int ltid = psched->tasks;
1489
[267]1490            // get vspace thread index
1491            unsigned int thread_id = task[task_id].trdid;
1492
[258]1493            if (ltid >= IDLE_TASK_INDEX) 
1494            {
1495                _puts("\n[BOOT ERROR] in boot_schedulers_init() : ");
1496                _putd( ltid );
1497                _puts(" tasks allocated to processor ");
1498                _putd( gpid );
1499                _puts(" / max is ");
1500                _putd( IDLE_TASK_INDEX );
1501                _puts("\n");
1502                _exit();
1503            }
1504
1505            // update the "tasks" and "current" fields in scheduler:
1506            // the first task to execute is task 0 as soon as there is at least
1507            // one task allocated to processor.
1508            psched->tasks   = ltid + 1;
1509            psched->current = 0;
1510
[436]1511            // initializes the task context
[452]1512            psched->context[ltid][CTX_CR_ID]     = 0;
1513            psched->context[ltid][CTX_SR_ID]     = ctx_sr;
1514            psched->context[ltid][CTX_SP_ID]     = ctx_sp;
1515            psched->context[ltid][CTX_EPC_ID]    = ctx_epc;
1516            psched->context[ltid][CTX_PTPR_ID]   = ctx_ptpr;
1517            psched->context[ltid][CTX_PTAB_ID]   = ctx_ptab;
1518            psched->context[ltid][CTX_LTID_ID]   = ltid;
1519            psched->context[ltid][CTX_GTID_ID]   = task_id;
1520            psched->context[ltid][CTX_TRDID_ID]  = thread_id;
1521            psched->context[ltid][CTX_VSID_ID]   = vspace_id;
1522            psched->context[ltid][CTX_RUN_ID]    = 1;
[258]1523
[452]1524            psched->context[ltid][CTX_TTY_ID]    = 0xFFFFFFFF;
1525            psched->context[ltid][CTX_CMA_FB_ID] = 0xFFFFFFFF;
1526            psched->context[ltid][CTX_CMA_RX_ID] = 0xFFFFFFFF;
1527            psched->context[ltid][CTX_CMA_TX_ID] = 0xFFFFFFFF;
1528            psched->context[ltid][CTX_NIC_RX_ID] = 0xFFFFFFFF;
1529            psched->context[ltid][CTX_NIC_TX_ID] = 0xFFFFFFFF;
1530            psched->context[ltid][CTX_TIM_ID]    = 0xFFFFFFFF;
1531            psched->context[ltid][CTX_HBA_ID]    = 0xFFFFFFFF;
[436]1532
[258]1533#if BOOT_DEBUG_SCHED
1534_puts("\nTask ");
1535_putd( task_id );
[295]1536_puts(" allocated to processor[");
[309]1537_putd( x );
[295]1538_puts(",");
[309]1539_putd( y );
[295]1540_puts(",");
[309]1541_putd( lpid );
[295]1542_puts("]\n  - ctx[LTID]   = ");
[258]1543_putd( psched->context[ltid][CTX_LTID_ID] );
1544_puts("\n  - ctx[SR]     = ");
1545_putx( psched->context[ltid][CTX_SR_ID] );
1546_puts("\n  - ctx[SP]     = ");
1547_putx( psched->context[ltid][CTX_SP_ID] );
1548_puts("\n  - ctx[EPC]    = ");
1549_putx( psched->context[ltid][CTX_EPC_ID] );
1550_puts("\n  - ctx[PTPR]   = ");
1551_putx( psched->context[ltid][CTX_PTPR_ID] );
1552_puts("\n  - ctx[PTAB]   = ");
1553_putx( psched->context[ltid][CTX_PTAB_ID] );
1554_puts("\n  - ctx[GTID]   = ");
[295]1555_putx( psched->context[ltid][CTX_GTID_ID] );
[258]1556_puts("\n  - ctx[VSID]   = ");
[295]1557_putx( psched->context[ltid][CTX_VSID_ID] );
[267]1558_puts("\n  - ctx[TRDID]  = ");
[295]1559_putx( psched->context[ltid][CTX_TRDID_ID] );
[258]1560_puts("\n");
1561#endif
1562
1563        } // end loop on tasks
1564    } // end loop on vspaces
[412]1565} // end boot_schedulers_init()
[258]1566
1567//////////////////////////////////////////////////////////////////////////////////
1568// This function loads the map.bin file from block device.
1569//////////////////////////////////////////////////////////////////////////////////
1570void boot_mapping_init()
1571{
[347]1572    // desactivates IOC interrupt
[289]1573    _ioc_init( 0 );
[258]1574
[347]1575    // open file "map.bin"
[295]1576    int fd_id = _fat_open( IOC_BOOT_MODE,
[258]1577                           "map.bin",
1578                           0 );         // no creation
1579    if ( fd_id == -1 )
1580    {
1581        _puts("\n[BOOT ERROR] : map.bin file not found \n");
1582        _exit();
1583    }
1584
1585#if BOOT_DEBUG_MAPPING
1586_puts("\n[BOOT] map.bin file successfully open at cycle ");
1587_putd(_get_proctime());
1588_puts("\n");
1589#endif
1590
[412]1591    // get "map.bin" file size (from fat) and check it
[258]1592    unsigned int size    = fat.fd[fd_id].file_size;
[347]1593
1594    if ( size > SEG_BOOT_MAPPING_SIZE )
1595    {
1596        _puts("\n[BOOT ERROR] : allocated segment too small for map.bin file\n");
1597        _exit();
1598    }
1599
1600    // load "map.bin" file into buffer
[258]1601    unsigned int nblocks = size >> 9;
1602    unsigned int offset  = size & 0x1FF;
1603    if ( offset ) nblocks++;
1604
[295]1605    unsigned int ok = _fat_read( IOC_BOOT_MODE,
[258]1606                                 fd_id, 
[321]1607                                 (unsigned int*)SEG_BOOT_MAPPING_BASE, 
[258]1608                                 nblocks,       
1609                                 0 );      // offset
1610    if ( ok == -1 )
1611    {
1612        _puts("\n[BOOT ERROR] : unable to load map.bin file \n");
1613        _exit();
1614    }
1615    _fat_close( fd_id );
1616   
[347]1617    // close file "map.bin"
[258]1618    boot_mapping_check();
[347]1619
[258]1620} // end boot_mapping_init()
1621
1622
[347]1623/////////////////////////////////////////////////////////////////////////////////////
1624// This function load all loadable segments for one .elf file, identified
1625// by the "pathname" argument. Some loadable segments can be copied in several
1626// clusters: same virtual address but different physical addresses. 
1627// - It open the file.
[359]1628// - It loads the complete file in the dedicated boot_elf_buffer.
1629// - It copies each loadable segments  at the virtual address defined in
1630//   the .elf file, making several copies if the target vseg is not local.
[347]1631// - It closes the file.
[359]1632// This function is supposed to be executed by processor[0,0,0].
[347]1633// Note:
1634//   We must use physical addresses to reach the destination buffers that
1635//   can be located in remote clusters. We use either a _physical_memcpy(),
1636//   or a _dma_physical_copy() if DMA is available.
1637//////////////////////////////////////////////////////////////////////////////////////
1638void load_one_elf_file( unsigned int is_kernel,     // kernel file if non zero
[258]1639                        char*        pathname,
[347]1640                        unsigned int vspace_id )    // to scan the proper vspace
[258]1641{
[347]1642    mapping_header_t  * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1643    mapping_vspace_t  * vspace  = _get_vspace_base(header);
1644    mapping_vseg_t    * vseg    = _get_vseg_base(header);
1645    mapping_vobj_t    * vobj    = _get_vobj_base(header);
1646
[258]1647    unsigned int seg_id;
1648
1649#if BOOT_DEBUG_ELF
1650_puts("\n[BOOT DEBUG] Start searching file ");
1651_puts( pathname );
1652_puts(" at cycle ");
1653_putd( _get_proctime() );
1654_puts("\n");
1655#endif
1656
1657    // open .elf file
[347]1658    int fd_id = _fat_open( IOC_BOOT_MODE,
[258]1659                           pathname,
1660                           0 );      // no creation
1661    if ( fd_id < 0 )
1662    {
1663        _puts("\n[BOOT ERROR] load_one_elf_file() : ");
1664        _puts( pathname );
1665        _puts(" not found\n");
1666        _exit();
1667    }
1668
[359]1669    // check buffer size versus file size
1670    if ( fat.fd[fd_id].file_size > GIET_ELF_BUFFER_SIZE )
[258]1671    {
1672        _puts("\n[BOOT ERROR] load_one_elf_file() : ");
1673        _puts( pathname );
[359]1674        _puts(" exceeds the GIET_ELF_BUFFERSIZE defined in giet_config.h\n");
[258]1675        _exit();
1676    }
1677
1678    // compute number of sectors
1679    unsigned int nbytes   = fat.fd[fd_id].file_size;
1680    unsigned int nsectors = nbytes>>9;
1681    if( nbytes & 0x1FF) nsectors++;
1682
[359]1683    // load file in elf buffer
[347]1684    if( _fat_read( IOC_BOOT_MODE, 
[258]1685                   fd_id, 
[359]1686                   boot_elf_buffer,
[258]1687                   nsectors,
1688                   0 ) != nsectors )
1689    {
1690        _puts("\n[BOOT ERROR] load_one_elf_file() : unexpected EOF for file ");
1691        _puts( pathname );
1692        _puts("\n");   
1693        _exit();
1694    }
1695
1696    // Check ELF Magic Number in ELF header
[359]1697    Elf32_Ehdr* elf_header_ptr = (Elf32_Ehdr*)boot_elf_buffer;
[258]1698
1699    if ( (elf_header_ptr->e_ident[EI_MAG0] != ELFMAG0) ||
1700         (elf_header_ptr->e_ident[EI_MAG1] != ELFMAG1) ||
1701         (elf_header_ptr->e_ident[EI_MAG2] != ELFMAG2) ||
1702         (elf_header_ptr->e_ident[EI_MAG3] != ELFMAG3) )
1703    {
1704        _puts("\n[BOOT ERROR] load_elf() : file ");
1705        _puts( pathname );
1706        _puts(" does not use ELF format\n");   
1707        _exit();
1708    }
1709
1710    // get program header table pointer
1711    unsigned int pht_index = elf_header_ptr->e_phoff;
1712    if( pht_index == 0 )
1713    {
1714        _puts("\n[BOOT ERROR] load_one_elf_file() : file ");
1715        _puts( pathname );
1716        _puts(" does not contain loadable segment\n");   
1717        _exit();
1718    }
[359]1719    Elf32_Phdr* elf_pht_ptr = (Elf32_Phdr*)(boot_elf_buffer + pht_index);
[258]1720
1721    // get number of segments
1722    unsigned int nsegments   = elf_header_ptr->e_phnum;
1723
[347]1724    _puts("\n[BOOT] File ");
1725    _puts( pathname );
1726    _puts(" loaded at cycle ");
1727    _putd( _get_proctime() );
1728    _puts("\n");
[258]1729
[347]1730    // Loop on loadable segments in the .elf file
[258]1731    for (seg_id = 0 ; seg_id < nsegments ; seg_id++)
1732    {
1733        if(elf_pht_ptr[seg_id].p_type == PT_LOAD)
1734        {
1735            // Get segment attributes
1736            unsigned int seg_vaddr  = elf_pht_ptr[seg_id].p_vaddr;
1737            unsigned int seg_offset = elf_pht_ptr[seg_id].p_offset;
1738            unsigned int seg_filesz = elf_pht_ptr[seg_id].p_filesz;
1739            unsigned int seg_memsz  = elf_pht_ptr[seg_id].p_memsz;
1740
[347]1741#if BOOT_DEBUG_ELF
1742_puts(" - segment ");
1743_putd( seg_id );
1744_puts(" / vaddr = ");
1745_putx( seg_vaddr );
1746_puts(" / file_size = ");
1747_putx( seg_filesz );
1748_puts("\n");
1749#endif
1750
[258]1751            if( seg_memsz < seg_filesz )
1752            {
1753                _puts("\n[BOOT ERROR] load_one_elf_file() : segment at vaddr = ");
1754                _putx( seg_vaddr );
1755                _puts(" in file ");
1756                _puts( pathname );
[359]1757                _puts(" has memsz < filesz \n");   
[258]1758                _exit();
1759            }
1760
1761            // fill empty space with 0 as required
1762            if( seg_memsz > seg_filesz )
1763            {
1764                unsigned int i; 
[359]1765                for( i = seg_filesz ; i < seg_memsz ; i++ ) boot_elf_buffer[i+seg_offset] = 0;
[258]1766            } 
1767
[359]1768            unsigned int src_vaddr = (unsigned int)boot_elf_buffer + seg_offset;
[258]1769
[347]1770            // search all vsegs matching the virtual address
1771            unsigned int vseg_first;
1772            unsigned int vseg_last;
1773            unsigned int vseg_id;
1774            unsigned int found = 0;
1775            if ( is_kernel )
1776            {
1777                vseg_first = 0;
1778                vseg_last  = header->globals;
1779            }
1780            else
1781            {
1782                vseg_first = vspace[vspace_id].vseg_offset;
1783                vseg_last  = vseg_first + vspace[vspace_id].vsegs;
1784            }
1785
1786            for ( vseg_id = vseg_first ; vseg_id < vseg_last ; vseg_id++ )
1787            {
1788                if ( seg_vaddr == vseg[vseg_id].vbase )  // matching
1789                {
1790                    found = 1;
1791
1792                    // get destination buffer physical address and size
1793                    paddr_t      seg_paddr  = vseg[vseg_id].pbase;
1794                    unsigned int vobj_id    = vseg[vseg_id].vobj_offset;
1795                    unsigned int seg_size   = vobj[vobj_id].length;
1796                   
[258]1797#if BOOT_DEBUG_ELF
[347]1798_puts("   loaded into vseg ");
1799_puts( vseg[vseg_id].name );
1800_puts(" at paddr = ");
1801_putl( seg_paddr );
1802_puts(" (buffer size = ");
1803_putx( seg_size );
1804_puts(")\n");
[258]1805#endif
[347]1806                    // check vseg size
1807                    if ( seg_size < seg_filesz )
1808                    {
1809                        _puts("\n[BOOT ERROR] in load_one_elf_file()\n");
1810                        _puts("vseg ");
1811                        _puts( vseg[vseg_id].name );
1812                        _puts(" is to small for loadable segment ");
1813                        _putx( seg_vaddr );
1814                        _puts(" in file ");
1815                        _puts( pathname );
1816                        _puts(" \n");   
1817                        _exit();
1818                    }
[258]1819
[347]1820                    // copy the segment from boot buffer to destination buffer
1821                    // using DMA channel[0,0,0] if it is available.
1822                    if( NB_DMA_CHANNELS > 0 )
1823                    {
1824                        _dma_physical_copy( 0,                  // DMA in cluster[0,0]
1825                                            0,                  // DMA channel 0
1826                                            (paddr_t)seg_paddr, // destination paddr
1827                                            (paddr_t)src_vaddr, // source paddr
1828                                            seg_filesz );       // size
1829                    }
1830                    else
1831                    {
1832                        _physical_memcpy( (paddr_t)seg_paddr,   // destination paddr
1833                                          (paddr_t)src_vaddr,   // source paddr
1834                                          seg_filesz );         // size
1835                    }
1836                }
1837            }  // end for vsegs in vspace
1838
1839            // check at least one matching vseg
1840            if ( found == 0 )
[258]1841            {
[347]1842                _puts("\n[BOOT ERROR] in load_one_elf_file()\n");
1843                _puts("vseg for loadable segment ");
1844                _putx( seg_vaddr );
1845                _puts(" in file ");
1846                _puts( pathname );
[436]1847                _puts(" not found: \n");   
1848                _puts(" check consistency between the .py and .ld files...\n");
[347]1849                _exit();
[258]1850            }
1851        }
[347]1852    }  // end for loadable segments
[258]1853
1854    // close .elf file
1855    _fat_close( fd_id );
1856
1857} // end load_one_elf_file()
1858
1859
[347]1860/////i////////////////////////////////////////////////////////////////////////////////
[258]1861// This function uses the map.bin data structure to load the "kernel.elf" file
[347]1862// as well as the various "application.elf" files into memory.
1863// - The "preloader.elf" file is not loaded, because it has been burned in the ROM.
1864// - The "boot.elf" file is not loaded, because it has been loaded by the preloader.
[295]1865// This function scans all vobjs defined in the map.bin data structure to collect
[347]1866// all .elf files pathnames, and calls the load_one_elf_file() for each .elf file.
1867// As the code can be replicated in several vsegs, the same code can be copied
1868// in one or several clusters by the load_one_elf_file() function.
1869//////////////////////////////////////////////////////////////////////////////////////
[258]1870void boot_elf_load()
1871{
[321]1872    mapping_header_t* header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
[258]1873    mapping_vspace_t* vspace = _get_vspace_base( header );
1874    mapping_vobj_t*   vobj   = _get_vobj_base( header );
1875    unsigned int      vspace_id;
1876    unsigned int      vobj_id;
1877    unsigned int      found;
1878
1879    // Scan all vobjs corresponding to global vsegs,
1880    // to find the pathname to the kernel.elf file
1881    found = 0;
1882    for( vobj_id = 0 ; vobj_id < header->globals ; vobj_id++ )
1883    {
1884        if(vobj[vobj_id].type == VOBJ_TYPE_ELF) 
1885        {   
1886            found = 1;
1887            break;
1888        }
1889    }
1890
1891    // We need one kernel.elf file
1892    if (found == 0)
1893    {
1894        _puts("[BOOT ERROR] boot_elf_load() : kernel.elf file not found\n");
1895        _exit();
1896    }
1897
[347]1898    // Load the kernel
1899    load_one_elf_file( 1,                           // kernel file
1900                       vobj[vobj_id].binpath,       // file pathname
[258]1901                       0 );                         // vspace 0
1902
[347]1903    // loop on the vspaces, scanning all vobjs in the vspace,
[258]1904    // to find the pathname of the .elf file associated to the vspace.
1905    for( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
1906    {
1907        // loop on the vobjs in vspace (vobj_id is the global index)
1908        unsigned int found = 0;
1909        for (vobj_id = vspace[vspace_id].vobj_offset;
1910             vobj_id < (vspace[vspace_id].vobj_offset + vspace[vspace_id].vobjs);
1911             vobj_id++) 
1912        {
1913            if(vobj[vobj_id].type == VOBJ_TYPE_ELF) 
1914            {   
1915                found = 1;
1916                break;
1917            }
1918        }
1919
1920        // We want one .elf file per vspace
1921        if (found == 0)
1922        {
1923            _puts("[BOOT ERROR] boot_elf_load() : .elf file not found for vspace ");
1924            _puts( vspace[vspace_id].name );
1925            _puts("\n");
1926            _exit();
1927        }
1928
[347]1929        load_one_elf_file( 0,                          // not a kernel file
1930                           vobj[vobj_id].binpath,      // file pathname
1931                           vspace_id );                // vspace index
[258]1932
1933    }  // end for vspaces
1934
1935} // end boot_elf_load()
1936
1937////////////////////////////////////////////////////////////////////////////////
1938// This function intializes the periherals and coprocessors, as specified
1939// in the mapping_info file.
1940////////////////////////////////////////////////////////////////////////////////
1941void boot_peripherals_init() 
1942{
[321]1943    mapping_header_t * header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
[258]1944    mapping_cluster_t * cluster = _get_cluster_base(header);
1945    mapping_periph_t * periph   = _get_periph_base(header);
1946    mapping_vobj_t * vobj       = _get_vobj_base(header);
1947    mapping_coproc_t * coproc   = _get_coproc_base(header);
1948    mapping_cp_port_t * cp_port = _get_cp_port_base(header);
[295]1949    mapping_irq_t * irq         = _get_irq_base(header);
[258]1950
1951    unsigned int cluster_id;
1952    unsigned int periph_id;
1953    unsigned int coproc_id;
1954    unsigned int cp_port_id;
1955    unsigned int channel_id;
1956
[263]1957    // loop on all physical clusters
1958    for (cluster_id = 0; cluster_id < X_SIZE*Y_SIZE; cluster_id++) 
[258]1959    {
[263]1960        // computes cluster coordinates
1961        unsigned int x          = cluster[cluster_id].x;
1962        unsigned int y          = cluster[cluster_id].y;
1963        unsigned int cluster_xy = (x<<Y_WIDTH) + y;
[258]1964
1965#if BOOT_DEBUG_PERI
[329]1966_puts("\n[BOOT DEBUG] Peripherals initialisation in cluster[");
[263]1967_putd( x );
1968_puts(",");
1969_putd( y );
[329]1970_puts("]\n");
[258]1971#endif
1972
[263]1973        // loop on peripherals
[258]1974        for (periph_id = cluster[cluster_id].periph_offset;
1975             periph_id < cluster[cluster_id].periph_offset +
1976             cluster[cluster_id].periphs; periph_id++) 
1977        {
1978            unsigned int type       = periph[periph_id].type;
[347]1979            unsigned int subtype    = periph[periph_id].subtype;
[258]1980            unsigned int channels   = periph[periph_id].channels;
1981
1982            switch (type) 
1983            {
1984                case PERIPH_TYPE_IOC:    // vci_block_device component
1985                {
[347]1986                    if ( subtype == PERIPH_SUBTYPE_BDV )
[289]1987                    {
[347]1988                        _bdv_lock.value = 0;
[258]1989#if BOOT_DEBUG_PERI
[347]1990_puts("- BDV : channels = ");
[263]1991_putd(channels);
1992_puts("\n");
[258]1993#endif
[347]1994                    }
1995                    else if ( subtype == PERIPH_SUBTYPE_HBA )
1996                    {
1997                        // TODO
1998                    }
1999                    else if ( subtype == PERIPH_SUBTYPE_SPI )
2000                    {
2001                        // TODO
2002                    }
[258]2003                    break;
2004                }
[263]2005                case PERIPH_TYPE_CMA:    // vci_chbuf_dma component
2006                {
2007                    for (channel_id = 0; channel_id < channels; channel_id++) 
2008                    {
2009                        // TODO
2010                    }
2011#if BOOT_DEBUG_PERI
[309]2012_puts("- CMA : channels = ");
[263]2013_putd(channels);
2014_puts("\n");
2015#endif
2016                    break;
2017                }
[258]2018                case PERIPH_TYPE_NIC:    // vci_multi_nic component
2019                {
2020                    for (channel_id = 0; channel_id < channels; channel_id++) 
2021                    {
2022                        // TODO
2023                    }
2024#if BOOT_DEBUG_PERI
[309]2025_puts("- NIC : channels = ");
[263]2026_putd(channels);
2027_puts("\n");
[258]2028#endif
2029                    break;
2030                }
[299]2031                case PERIPH_TYPE_TTY:    // vci_multi_tty component
[263]2032                {
[347]2033                    for (channel_id = 0; channel_id < channels; channel_id++) 
2034                    {
2035                        _tty_lock[channel_id].value = 0;
2036                        _tty_rx_full[channel_id]    = 0;
2037                    }
[263]2038#if BOOT_DEBUG_PERI
[309]2039_puts("- TTY : channels = ");
[263]2040_putd(channels);
2041_puts("\n");
2042#endif
2043                    break;
2044                }
[299]2045                case PERIPH_TYPE_IOB:    // vci_io_bridge component
[258]2046                {
[299]2047                    if (GIET_USE_IOMMU) 
[258]2048                    {
2049                        // TODO
2050                        // get the iommu page table physical address
2051                        // set IOMMU page table address
2052                        // pseg_base[IOB_IOMMU_PTPR] = ptab_pbase;   
2053                        // activate IOMMU
2054                        // pseg_base[IOB_IOMMU_ACTIVE] = 1;       
2055                    }
2056                    break;
2057                }
[295]2058                case PERIPH_TYPE_PIC:    // vci_iopic component
2059                {
2060#if BOOT_DEBUG_PERI
[309]2061_puts("- PIC : channels = ");
[295]2062_putd(channels);
2063_puts("\n");
2064#endif
[309]2065                    // scan all IRQs defined in mapping for PIC component,
[295]2066                    // and initialises addresses for WTI IRQs
2067                    for ( channel_id = periph[periph_id].irq_offset ;
2068                          channel_id < periph[periph_id].irq_offset + periph[periph_id].irqs ;
2069                          channel_id++ )
2070                    {
[321]2071                        unsigned int hwi_id     = irq[channel_id].srcid;   // HWI index in PIC
2072                        unsigned int wti_id     = irq[channel_id].dest_id; // WTI index in XCU
2073                        unsigned int cluster_xy = irq[channel_id].dest_xy; // XCU coordinates
[295]2074                        unsigned int vaddr;
2075
2076                        _xcu_get_wti_address( wti_id, &vaddr );
[412]2077                        _pic_init( hwi_id, vaddr, cluster_xy ); 
[295]2078
2079#if BOOT_DEBUG_PERI
[412]2080unsigned int address = _pic_get_register( channel_id, IOPIC_ADDRESS );
2081unsigned int extend  = _pic_get_register( channel_id, IOPIC_EXTEND  );
[295]2082_puts("    hwi_index = ");
2083_putd( hwi_id );
2084_puts(" / wti_index = ");
2085_putd( wti_id );
2086_puts(" / vaddr = ");
2087_putx( vaddr );
2088_puts(" in cluster[");
[321]2089_putd( cluster_xy >> Y_WIDTH );
[295]2090_puts(",");
[321]2091_putd( cluster_xy & ((1<<Y_WIDTH)-1) );
[412]2092_puts("] / checked_xcu_paddr = ");
2093_putl( (paddr_t)address + (((paddr_t)extend)<<32) );
2094_puts("\n");
[295]2095#endif
2096                    }
2097                    break;
2098                }
[258]2099            }  // end switch periph type
2100        }  // end for periphs
2101
2102#if BOOT_DEBUG_PERI
[329]2103_puts("\n[BOOT DEBUG] Coprocessors initialisation in cluster[");
[263]2104_putd( x );
2105_puts(",");
2106_putd( y );
[329]2107_puts("]\n");
[258]2108#endif
2109
[263]2110        // loop on coprocessors
[258]2111        for ( coproc_id = cluster[cluster_id].coproc_offset;
2112              coproc_id < cluster[cluster_id].coproc_offset +
2113              cluster[cluster_id].coprocs; coproc_id++ ) 
2114        {
2115
2116#if BOOT_DEBUG_PERI
2117_puts("- coprocessor name : ");
2118_puts(coproc[coproc_id].name);
2119_puts(" / nb ports = ");
2120_putd((unsigned int) coproc[coproc_id].ports);
2121_puts("\n");
2122#endif
2123            // loop on the coprocessor ports
2124            for ( cp_port_id = coproc[coproc_id].port_offset;
2125                  cp_port_id < coproc[coproc_id].port_offset + coproc[coproc_id].ports;
2126                  cp_port_id++ ) 
2127            {
[412]2128                // get global index of associted vobj
[321]2129                unsigned int vobj_id   = cp_port[cp_port_id].mwmr_vobj_id; 
[258]2130
[412]2131                // get MWMR channel base address
2132                page_table_t* ptab  = (page_table_t*)_ptabs_vaddr[0][x][y];
2133                unsigned int  vbase = vobj[vobj_id].vbase;
2134                unsigned int  ppn;
2135                unsigned int  flags;
2136                paddr_t       pbase;
[258]2137
[412]2138                _v2p_translate( ptab, 
2139                                vbase>>12 , 
2140                                &ppn, 
2141                                &flags );
2142
2143                pbase = ((paddr_t)ppn)<<12;
2144
2145                // initialise cp_port
[263]2146                _mwr_hw_init( cluster_xy,
2147                              cp_port_id, 
2148                              cp_port[cp_port_id].direction, 
[412]2149                              pbase );
[258]2150#if BOOT_DEBUG_PERI
2151_puts("     port direction: ");
2152_putd( (unsigned int)cp_port[cp_port_id].direction );
2153_puts(" / mwmr_channel_pbase = ");
[412]2154_putl( pbase );
[258]2155_puts(" / name = ");
2156_puts(vobj[vobj_id].name);
2157_puts("\n"); 
2158#endif
2159            } // end for cp_ports
2160        } // end for coprocs
2161    } // end for clusters
2162} // end boot_peripherals_init()
2163
2164/////////////////////////////////////////////////////////////////////////
[412]2165// This function initialises the physical memory allocators in each
2166// cluster containing a RAM pseg.
2167/////////////////////////////////////////////////////////////////////////
2168void boot_pmem_init() 
2169{
2170    mapping_header_t*  header     = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
2171    mapping_cluster_t* cluster    = _get_cluster_base(header);
2172    mapping_pseg_t*    pseg       = _get_pseg_base(header);
2173
2174    unsigned int cluster_id;
2175    unsigned int pseg_id;
2176
2177    // scan all clusters
2178    for ( cluster_id = 0 ; cluster_id < X_SIZE*Y_SIZE ; cluster_id++ ) 
2179    {
2180        // scan the psegs in cluster to find first pseg of type RAM
2181        unsigned int pseg_min = cluster[cluster_id].pseg_offset;
2182        unsigned int pseg_max = pseg_min + cluster[cluster_id].psegs;
2183        for ( pseg_id = pseg_min ; pseg_id < pseg_max ; pseg_id++ )
2184        {
2185            if ( pseg[pseg_id].type == PSEG_TYPE_RAM )
2186            {
2187                unsigned int x    = cluster[cluster_id].x;
2188                unsigned int y    = cluster[cluster_id].y;
2189                unsigned int base = (unsigned int)pseg[pseg_id].base;
2190                unsigned int size = (unsigned int)pseg[pseg_id].length;
2191                _pmem_alloc_init( x, y, base, size );
2192
2193#if BOOT_DEBUG_PT
2194_puts("\n[BOOT DEBUG] pmem allocator initialised in cluster[");
2195_putd( x );
2196_puts(",");
2197_putd( y );
2198_puts("] base = ");
2199_putx( base );
2200_puts(" / size = ");
2201_putx( size );
2202_puts("\n");
2203#endif
2204               break;
2205            }
2206        }
2207    }
2208} // end boot_pmem_init()
2209 
2210/////////////////////////////////////////////////////////////////////////
[258]2211// This function is the entry point of the boot code for all processors.
2212// Most of this code is executed by Processor 0 only.
2213/////////////////////////////////////////////////////////////////////////
[347]2214void boot_init() 
[258]2215{
[321]2216    mapping_header_t*  header     = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
[295]2217    mapping_cluster_t* cluster    = _get_cluster_base(header);
2218    unsigned int       gpid       = _get_procid();
[258]2219 
[263]2220    if ( gpid == 0 )    // only Processor 0 does it
[258]2221    {
2222        _puts("\n[BOOT] boot_init start at cycle ");
2223        _putd(_get_proctime());
2224        _puts("\n");
2225
[347]2226        // Load the map.bin file into memory and check it
[258]2227        boot_mapping_init();
2228
[295]2229        _puts("\n[BOOT] Mapping \"");
[258]2230        _puts( header->name );
[295]2231        _puts("\" loaded at cycle ");
[258]2232        _putd(_get_proctime());
2233        _puts("\n");
2234
[412]2235        // Initializes the physical memory allocators
2236        boot_pmem_init();
2237
2238        _puts("\n[BOOT] Physical memory allocators initialised at cycle ");
2239        _putd(_get_proctime());
2240        _puts("\n");
2241
[347]2242        // Build page tables
[436]2243        boot_ptabs_init();
[258]2244
[412]2245        _puts("\n[BOOT] Page tables initialised at cycle ");
2246        _putd(_get_proctime());
2247        _puts("\n");
2248
[347]2249        // Activate MMU for proc [0,0,0]
2250        _set_mmu_ptpr( (unsigned int)(_ptabs_paddr[0][0][0]>>13) );
[258]2251        _set_mmu_mode( 0xF );
2252
[263]2253        _puts("\n[BOOT] Processor[0,0,0] : MMU activation at cycle ");
[258]2254        _putd(_get_proctime());
2255        _puts("\n");
2256
[347]2257        // Initialise private vobjs in vspaces
[258]2258        boot_vobjs_init();
2259
2260        _puts("\n[BOOT] Private vobjs initialised at cycle ");
2261        _putd(_get_proctime());
2262        _puts("\n");
[452]2263 
[347]2264        // Initialise schedulers
[258]2265        boot_schedulers_init();
2266
[295]2267        _puts("\n[BOOT] Schedulers initialised at cycle ");
[258]2268        _putd(_get_proctime());
2269        _puts("\n");
2270       
[347]2271        // Set CP0_SCHED register for proc [0,0,0]
2272        _set_sched( (unsigned int)_schedulers[0][0][0] );
[258]2273
[347]2274        // Initialise non replicated peripherals
[258]2275        boot_peripherals_init();
2276
[295]2277        _puts("\n[BOOT] Non replicated peripherals initialised at cycle ");
[258]2278        _putd(_get_proctime());
2279        _puts("\n");
2280
2281        // Loading all .elf files
2282        boot_elf_load();
2283
[295]2284        // P0 starts all other processors
2285        unsigned int clusterid, p;
[258]2286
[295]2287        for ( clusterid = 0 ; clusterid < X_SIZE*Y_SIZE ; clusterid++ ) 
[258]2288        {
[295]2289            unsigned int nprocs     = cluster[clusterid].procs;
[347]2290            unsigned int x          = cluster[clusterid].x;
2291            unsigned int y          = cluster[clusterid].y;
2292            unsigned int cluster_xy = (x<<Y_WIDTH) + y;
[295]2293
2294            for ( p = 0 ; p < nprocs; p++ ) 
[258]2295            {
[295]2296                if ( (nprocs > 0) && ((clusterid != 0) || (p != 0)) )
[258]2297                {
[366]2298                    _xcu_send_wti( cluster_xy, p, (unsigned int)boot_entry );
[258]2299                }
2300            }
2301        }
[295]2302 
[258]2303    }  // end monoprocessor boot
2304
[356]2305    ///////////////////////////////////////////////////////////////////////////////
2306    //            Parallel execution starts actually here
2307    ///////////////////////////////////////////////////////////////////////////////
2308
2309    // all processor initialise the SCHED register
2310    // from the _schedulers[x][y][lpid array]
[427]2311    unsigned int cluster_xy = gpid >> P_WIDTH;
2312    unsigned int lpid       = gpid & ((1<<P_WIDTH)-1);
[347]2313    unsigned int x          = cluster_xy >> Y_WIDTH;
2314    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
2315    _set_sched( (unsigned int)_schedulers[x][y][lpid] );
[258]2316
[347]2317    // all processors (but Proc[0,0,0]) activate MMU
[263]2318    if ( gpid != 0 )
[258]2319    {
[347]2320        _set_mmu_ptpr( (unsigned int)(_ptabs_paddr[0][x][y]>>13) );
[258]2321        _set_mmu_mode( 0xF );
2322    }
2323
[427]2324    // all processors reset BEV bit in the status register to use
2325    // the GIET_VM exception handler instead of the PRELOADER exception handler
2326    _set_sr( 0 );
2327
[356]2328    // all processors jump to kernel_init
2329    // using the address defined in the giet_vsegs.ld file
[321]2330    unsigned int kernel_entry = (unsigned int)&kernel_init_vbase;
[258]2331    asm volatile( "jr   %0" ::"r"(kernel_entry) );
2332
2333} // end boot_init()
2334
2335
2336// Local Variables:
2337// tab-width: 4
2338// c-basic-offset: 4
2339// c-file-offsets:((innamespace . 0)(inline-open . 0))
2340// indent-tabs-mode: nil
2341// End:
2342// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
2343
Note: See TracBrowser for help on using the repository browser.