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

Last change on this file since 278 was 276, checked in by cfuguet, 10 years ago

Adding some information on debug messages and fixing
old variable names

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