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

Last change on this file since 357 was 356, checked in by alain, 10 years ago

Bloup...

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