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

Last change on this file since 363 was 359, checked in by alain, 10 years ago

1/ Introduce the boot.S file that is the entry point
in the GIET-VM bootloader: The GIET-VM does not use
the preloader stack anymore, but uses its own stack
2/ Remove the seg_boot_buffer segment for the boot-loader.
The buffer used to load a complete .elf segment is defined
as a global variable in the seg_boot_data segment.
The GIET_ELF_BUFFER_SIZE is defined in the giet_config.h file.

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