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

Last change on this file since 492 was 490, checked in by haoliu, 10 years ago

Implemented a new way to construct the ptabs in boot. In the map.bin file,
each physical segment in cluster[x][y] is handled by the processor[x][y][0]. So
the constrcuting of page table is done in parrallel by all the
processor[x][y][0] at the same time.

This way spents less time than the constructing sequential by one processor(
the processor[0][0][0])

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