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

Last change on this file since 263 was 263, checked in by alain, 11 years ago

Introducing support for TSAR fixed format cluster index (cluster_xy)
We have now 4 parameters defined in map.xml:

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