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

Last change on this file since 532 was 527, checked in by alain, 10 years ago

1) Introducing dynamic routing of external IRQs when the platform
contains an IOPIC component.
2) Improving parallel boot for elf files: The FAT access is done by
P[0,0,0] only, but the code replication in all cluster is done
in parallel by all P[x,y,0] processors.

File size: 77.9 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : boot.c
3// Date     : 01/11/2013
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// The boot.c file contains the bootloader for the GIET-VM static OS. 
8//
9// This code 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 type (unsigned long long).
12// It natively supports clusterised shared memory multi-processors architectures,
13// where each processor is identified by a composite index [x,y,p],
14// and where there is one physical memory bank per cluster.
15//
16// The boot.elf file is stored on disk and is loaded into memory by proc[0,0,0],
17// executing the generic preloader (stored in ROM). The boot-loader code itself
18// is executed in parallel by all proc[x,y,0], and performs the following tasks:
19// - load into memory various binary files, from a FAT32 file system.
20// - build the various page tables (one page table per vspace).
21// - initialize the shedulers (one scheduler per processor).
22// - initialize the external peripherals.
23//
24// 1) The binary files to be loaded are:
25//    - the "map.bin" file contains the hardware architecture description and the
26//      mapping directives. It must be stored in the the seg_boot_mapping segment
27//      (at address SEG_BOOT_MAPPING_BASE defined in hard_config.h file).
28//    - the "kernel.elf" file contains the kernel binary code and data.
29//    - the various "application.elf" files.
30//
31// 2) The "map.bin" file contains the C binary structure defining:
32//    - the hardware architecture: number of clusters, number or processors,
33//      size of the memory segments, and peripherals in each cluster.
34//    - The structure of the various multi-threaded software applications:
35//      number of tasks, communication channels.
36//    - The mapping: placement of virtual segments (vseg) in the physical
37//      segments (pseg), placement of software tasks on the processors,
38//
39// 3) The GIET-VM uses the paged virtual memory to provides two services:
40//    - classical memory protection, when several independant applications compiled
41//      in different virtual spaces are executing on the same hardware platform.
42//    - data placement in NUMA architectures, to control the placement
43//      of the software objects (vsegs) on the physical memory banks (psegs).
44//
45//    The max number of vspaces (GIET_NB_VSPACE_MAX) is a configuration parameter.
46//    For each application, the tasks are statically allocateded on processors.
47//    The page table are statically build in the boot phase, and they do not
48//    change during execution.
49//    The GIET_VM uses both small pages (4 Kbytes), and big pages (2 Mbytes).
50//
51//    Each page table (one page table per virtual space) is monolithic, and
52//    contains one PT1 (8 Kbytes) and a variable number of PT2s (4 Kbytes each).
53//    For each vspace, the number of PT2s is defined by the size of the PTAB vseg
54//    in the mapping.
55//    The PT1 is indexed by the ix1 field (11 bits) of the VPN. An entry is 32 bits.
56//    A PT2 is indexed the ix2 field (9 bits) of the VPN. An entry is 64 bits.
57//    The first word contains the flags, the second word contains the PPN.
58//    The page tables are distributed/replicated in all clusters.
59///////////////////////////////////////////////////////////////////////////////////
60// Implementation Notes:
61//
62// 1) The cluster_id variable is a linear index in the mapping_info array.
63//    The cluster_xy variable is the tological index = x << Y_WIDTH + y
64//
65// 2) We set the _tty0_boot_mode variable to force the _printf() function to use
66//    the tty0_spin_lock for exclusive access to TTY0.
67///////////////////////////////////////////////////////////////////////////////////
68
69#include <giet_config.h>
70#include <hard_config.h>
71#include <mapping_info.h>
72#include <kernel_malloc.h>
73#include <memspace.h>
74#include <tty_driver.h>
75#include <xcu_driver.h>
76#include <bdv_driver.h>
77#include <hba_driver.h>
78#include <sdc_driver.h>
79#include <cma_driver.h>
80#include <nic_driver.h>
81#include <iob_driver.h>
82#include <pic_driver.h>
83#include <mwr_driver.h>
84#include <dma_driver.h>
85#include <ctx_handler.h>
86#include <irq_handler.h>
87#include <vmem.h>
88#include <pmem.h>
89#include <utils.h>
90#include <tty0.h>
91#include <kernel_locks.h>
92#include <kernel_barriers.h>
93#include <elf-types.h>
94#include <fat32.h>
95#include <mips32_registers.h>
96#include <stdarg.h>
97
98#if !defined(X_SIZE)
99# error: The X_SIZE value must be defined in the 'hard_config.h' file !
100#endif
101
102#if !defined(Y_SIZE)
103# error: The Y_SIZE value must be defined in the 'hard_config.h' file !
104#endif
105
106#if !defined(X_WIDTH)
107# error: The X_WIDTH value must be defined in the 'hard_config.h' file !
108#endif
109
110#if !defined(Y_WIDTH)
111# error: The Y_WIDTH value must be defined in the 'hard_config.h' file !
112#endif
113
114#if !defined(SEG_BOOT_MAPPING_BASE)
115# error: The SEG_BOOT_MAPPING_BASE value must be defined in the hard_config.h file !
116#endif
117
118#if !defined(NB_PROCS_MAX)
119# error: The NB_PROCS_MAX value must be defined in the 'hard_config.h' file !
120#endif
121
122#if !defined(GIET_NB_VSPACE_MAX)
123# error: The GIET_NB_VSPACE_MAX value must be defined in the 'giet_config.h' file !
124#endif
125
126#if !defined(GIET_ELF_BUFFER_SIZE)
127# error: The GIET_ELF_BUFFER_SIZE value must be defined in the giet_config.h file !
128#endif
129
130////////////////////////////////////////////////////////////////////////////
131//      Global variables for boot code
132////////////////////////////////////////////////////////////////////////////
133
134// FAT internal representation for boot code 
135__attribute__((section(".kdata")))
136fat32_fs_t  _fat   __attribute__((aligned(512)));
137
138// Temporaty buffer used to load one complete .elf file 
139__attribute__((section(".kdata")))
140char  _boot_elf_buffer[GIET_ELF_BUFFER_SIZE] __attribute__((aligned(512)));
141
142// Physical memory allocators array (one per cluster)
143__attribute__((section(".kdata")))
144pmem_alloc_t  boot_pmem_alloc[X_SIZE][Y_SIZE];
145
146// Distributed kernel heap (one per cluster)
147// __attribute__((section(".kdata")))
148// kernel_heap_t       kernel_heap[X_SIZE][Y_SIZE];
149
150// Schedulers virtual base addresses array (one per processor)
151__attribute__((section(".kdata")))
152static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX];
153
154// Page tables virtual base addresses (one per vspace and per cluster)
155__attribute__((section(".kdata")))
156unsigned int        _ptabs_vaddr[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
157
158// Page tables physical base addresses (one per vspace and per cluster)
159__attribute__((section(".kdata")))
160paddr_t             _ptabs_paddr[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
161
162// Page tables pt2 allocators (one per vspace and per cluster)
163__attribute__((section(".kdata")))
164unsigned int        _ptabs_next_pt2[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
165
166// Page tables max_pt2  (same value for all page tables)
167__attribute__((section(".kdata")))
168unsigned int        _ptabs_max_pt2;
169
170// boot code uses a spin lock to protect TTY0
171__attribute__((section(".kdata")))
172unsigned int        _tty0_boot_mode = 1;
173
174__attribute__((section(".kdata")))
175spin_lock_t         _ptabs_spin_lock[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE];
176
177// barrier used by boot code for parallel execution
178__attribute__((section(".kdata")))
179simple_barrier_t    _barrier_all_clusters;
180
181//////////////////////////////////////////////////////////////////////////////
182//        Extern variables
183//////////////////////////////////////////////////////////////////////////////
184
185// this variable is defined in the tty0.c file
186extern spin_lock_t  _tty0_spin_lock;
187
188extern void boot_entry();
189
190//////////////////////////////////////////////////////////////////////////////
191// This function registers a new PTE1 in the page table defined
192// by the vspace_id argument, and the (x,y) coordinates.
193// It updates only the first level PT1.
194// As each vseg is mapped by a different processor, the PT1 entry cannot
195// be concurrently accessed, and we don't need to take any lock.
196//////////////////////////////////////////////////////////////////////////////
197void boot_add_pte1( unsigned int vspace_id,
198                    unsigned int x,
199                    unsigned int y,
200                    unsigned int vpn,        // 20 bits right-justified
201                    unsigned int flags,      // 10 bits left-justified
202                    unsigned int ppn )       // 28 bits right-justified
203{
204    // compute index in PT1
205    unsigned int    ix1 = vpn >> 9;         // 11 bits for ix1
206
207    // get page table physical base address
208    paddr_t  pt1_pbase = _ptabs_paddr[vspace_id][x][y];
209
210    if ( pt1_pbase == 0 )
211    {
212        _printf("\n[BOOT ERROR] in boot_add_pte1() : no PTAB in cluster[%d,%d]"
213                    " containing processors\n", x , y );
214        _exit();
215    }
216
217    // compute pte1 : 2 bits V T / 8 bits flags / 3 bits RSVD / 19 bits bppi
218    unsigned int    pte1 = PTE_V |
219                           (flags & 0x3FC00000) |
220                           ((ppn>>9) & 0x0007FFFF);
221
222    // write pte1 in PT1
223    _physical_write( pt1_pbase + 4*ix1, pte1 );
224
225    asm volatile ("sync");
226
227}   // end boot_add_pte1()
228
229//////////////////////////////////////////////////////////////////////////////
230// This function registers a new PTE2 in the page table defined
231// by the vspace_id argument, and the (x,y) coordinates.
232// It updates both the first level PT1 and the second level PT2.
233// As the set of PT2s is implemented as a fixed size array (no dynamic
234// allocation), this function checks a possible overflow of the PT2 array.
235// As a given entry in PT1 can be shared by several vsegs, mapped by
236// different processors, we need to take the lock protecting PTAB[v][x]y].
237//////////////////////////////////////////////////////////////////////////////
238void boot_add_pte2( unsigned int vspace_id,
239                    unsigned int x,
240                    unsigned int y,
241                    unsigned int vpn,        // 20 bits right-justified
242                    unsigned int flags,      // 10 bits left-justified
243                    unsigned int ppn )       // 28 bits right-justified
244{
245    unsigned int ix1;
246    unsigned int ix2;
247    paddr_t      pt2_pbase;     // PT2 physical base address
248    paddr_t      pte2_paddr;    // PTE2 physical address
249    unsigned int pt2_id;        // PT2 index
250    unsigned int ptd;           // PTD : entry in PT1
251
252    ix1 = vpn >> 9;             // 11 bits for ix1
253    ix2 = vpn & 0x1FF;          //  9 bits for ix2
254
255    // get page table physical base address
256    paddr_t      pt1_pbase = _ptabs_paddr[vspace_id][x][y];
257
258    if ( pt1_pbase == 0 )
259    {
260        _printf("\n[BOOT ERROR] in boot_add_pte2() : no PTAB for vspace %d "
261                "in cluster[%d,%d]\n", vspace_id , x , y );
262        _exit();
263    }
264
265    // get lock protecting PTAB[vspace_id][x][y]
266    _spin_lock_acquire( &_ptabs_spin_lock[vspace_id][x][y] );
267
268    // get ptd in PT1
269    ptd = _physical_read( pt1_pbase + 4 * ix1 );
270
271    if ((ptd & PTE_V) == 0)    // undefined PTD: compute PT2 base address,
272                               // and set a new PTD in PT1
273    {
274        // get a new pt2_id
275        pt2_id = _ptabs_next_pt2[vspace_id][x][y];
276        _ptabs_next_pt2[vspace_id][x][y] = pt2_id + 1;
277
278        // check overflow
279        if (pt2_id == _ptabs_max_pt2) 
280        {
281            _printf("\n[BOOT ERROR] in boot_add_pte2() : PTAB[%d,%d,%d]"
282                    " contains not enough PT2s\n", vspace_id, x, y );
283            _exit();
284        }
285
286        pt2_pbase = pt1_pbase + PT1_SIZE + PT2_SIZE * pt2_id;
287        ptd = PTE_V | PTE_T | (unsigned int) (pt2_pbase >> 12);
288
289        // set PTD into PT1
290        _physical_write( pt1_pbase + 4*ix1, ptd);
291    }
292    else                       // valid PTD: compute PT2 base address
293    {
294        pt2_pbase = ((paddr_t)(ptd & 0x0FFFFFFF)) << 12;
295    }
296
297    // set PTE in PT2 : flags & PPN in two 32 bits words
298    pte2_paddr  = pt2_pbase + 8 * ix2;
299    _physical_write(pte2_paddr     , (PTE_V | flags) );
300    _physical_write(pte2_paddr + 4 , ppn );
301
302    // release lock protecting PTAB[vspace_id][x][y]
303    _spin_lock_release( &_ptabs_spin_lock[vspace_id][x][y] );
304
305    asm volatile ("sync");
306
307}   // end boot_add_pte2()
308
309////////////////////////////////////////////////////////////////////////////////////
310// Align the value of paddr or vaddr to the required alignement,
311// defined by alignPow2 == L2(alignement).
312////////////////////////////////////////////////////////////////////////////////////
313paddr_t paddr_align_to( paddr_t paddr, unsigned int alignPow2 ) 
314{
315    paddr_t mask = (1 << alignPow2) - 1;
316    return ((paddr + mask) & ~mask);
317}
318
319unsigned int vaddr_align_to( unsigned int vaddr, unsigned int alignPow2 ) 
320{
321    unsigned int mask = (1 << alignPow2) - 1;
322    return ((vaddr + mask) & ~mask);
323}
324
325/////////////////////////////////////////////////////////////////////////////////////
326// This function map a vseg identified by the vseg pointer.
327//
328// A given vseg can be mapped in a Big Physical Pages (BPP: 2 Mbytes) or in a
329// Small Physical Pages (SPP: 4 Kbytes), depending on the "big" attribute of vseg,
330// with the following rules:
331// - SPP : There is only one vseg in a small physical page, but a single vseg
332//   can cover several contiguous small physical pages.
333// - BPP : It can exist several vsegs in a single big physical page, and a single
334//   vseg can cover several contiguous big physical pages.
335//
336// 1) First step: it computes various vseg attributes and checks
337//    alignment constraints.
338//
339// 2) Second step: it allocates the required number of contiguous physical pages,
340//    computes the physical base address (if the vseg is not identity mapping),
341//    and register it in the vseg pbase field.
342//    Only the vsegs used by the boot code and the peripheral vsegs
343//    can be identity mapping. The first big physical page in cluster[0,0]
344//    is reserved for the boot vsegs.
345//
346// 3) Third step (only for vseg that have the VSEG_TYPE_PTAB): the M page tables
347//    associated to the M vspaces must be packed in the same vseg.
348//    We divide this vseg in M sub-segments, and compute the vbase and pbase
349//    addresses for M page tables, and register these addresses in the _ptabs_paddr
350//    and _ptabs_vaddr arrays.
351// 
352/////////////////////////////////////////////////////////////////////////////////////
353void boot_vseg_map( mapping_vseg_t* vseg,
354                    unsigned int    vspace_id )
355{
356    mapping_header_t*   header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
357    mapping_cluster_t*  cluster = _get_cluster_base(header);
358    mapping_pseg_t*     pseg    = _get_pseg_base(header);
359
360    //////////// First step : compute vseg attributes
361
362    // compute destination cluster pointer & coordinates
363    pseg    = pseg + vseg->psegid;
364    cluster = cluster + pseg->clusterid;
365    unsigned int        x_dest     = cluster->x;
366    unsigned int        y_dest     = cluster->y;
367
368    // compute the "big" vseg attribute
369    unsigned int        big = vseg->big;
370
371    // all vsegs must be aligned on 4Kbytes
372    if ( vseg->vbase & 0x00000FFF ) 
373    {
374        _printf("\n[BOOT ERROR] vseg %s not aligned : vbase = %x\n", 
375                vseg->name, vseg->vbase );
376        _exit();
377    }
378
379    // compute the "is_ram" vseg attribute
380    unsigned int        is_ram;
381    if ( pseg->type == PSEG_TYPE_RAM )  is_ram = 1;
382    else                                is_ram = 0;
383
384    // compute the "is_ptab" attribute
385    unsigned int        is_ptab;
386    if ( vseg->type == VSEG_TYPE_PTAB ) is_ptab = 1;
387    else                                is_ptab = 0;
388
389    // compute actual vspace index
390    unsigned int vsid;
391    if ( vspace_id == 0xFFFFFFFF ) vsid = 0;
392    else                           vsid = vspace_id;
393
394    //////////// Second step : compute ppn and npages 
395    //////////// - if identity mapping :  ppn <= vpn
396    //////////// - if vseg is periph   :  ppn <= pseg.base >> 12
397    //////////// - if vseg is ram      :  ppn <= physical memory allocator
398
399    unsigned int ppn;          // first physical page index (28 bits = |x|y|bppi|sppi|)
400    unsigned int vpn;          // first virtual page index  (20 bits = |ix1|ix2|)
401    unsigned int vpn_max;      // last  virtual page index  (20 bits = |ix1|ix2|)
402
403    vpn     = vseg->vbase >> 12;
404    vpn_max = (vseg->vbase + vseg->length - 1) >> 12;
405
406    // compute npages
407    unsigned int npages;       // number of required (big or small) pages
408    if ( big == 0 ) npages  = vpn_max - vpn + 1;            // number of small pages
409    else            npages  = (vpn_max>>9) - (vpn>>9) + 1;  // number of big pages
410
411    // compute ppn
412    if ( vseg->ident )           // identity mapping
413    {
414        ppn = vpn;
415    }
416    else                         // not identity mapping
417    {
418        if ( is_ram )            // RAM : physical memory allocation required
419        {
420            // compute pointer on physical memory allocator in dest cluster
421            pmem_alloc_t*     palloc = &boot_pmem_alloc[x_dest][y_dest];
422
423            if ( big == 0 )             // SPP : small physical pages
424            {
425                // allocate contiguous small physical pages
426                ppn = _get_small_ppn( palloc, npages );
427            }
428            else                            // BPP : big physical pages
429            {
430 
431                // one big page can be shared by several vsegs
432                // we must chek if BPP already allocated
433                if ( is_ptab )   // It cannot be mapped
434                {
435                    ppn = _get_big_ppn( palloc, npages ); 
436                }
437                else             // It can be mapped
438                {
439                    unsigned int ix1   = vpn >> 9;   // 11 bits
440                    paddr_t      paddr = _ptabs_paddr[vsid][x_dest][y_dest] + (ix1<<2);
441                    unsigned int pte1  = _physical_read( paddr );
442
443                    if ( (pte1 & PTE_V) == 0 )     // BPP not allocated yet
444                    {
445                        // allocate contiguous big physical pages
446                        ppn = _get_big_ppn( palloc, npages );
447                    }
448                    else                           // BPP already allocated
449                    {
450                        // test if new vseg has the same mode bits than
451                        // the other vsegs in the same big page
452                        unsigned int pte1_mode = 0;
453                        if (pte1 & PTE_C) pte1_mode |= C_MODE_MASK;
454                        if (pte1 & PTE_X) pte1_mode |= X_MODE_MASK;
455                        if (pte1 & PTE_W) pte1_mode |= W_MODE_MASK;
456                        if (pte1 & PTE_U) pte1_mode |= U_MODE_MASK;
457                        if (vseg->mode != pte1_mode) 
458                        {
459                            _printf("\n[BOOT ERROR] in boot_vseg_map() : "
460                                    "vseg %s has different flags than another vseg "
461                                    "in the same BPP\n", vseg->name );
462                            _exit();
463                        }
464                        ppn = ((pte1 << 9) & 0x0FFFFE00);
465                    }
466                }
467                ppn = ppn | (vpn & 0x1FF);
468            }
469        }
470        else                    // PERI : no memory allocation required
471        {
472            ppn = pseg->base >> 12;
473        }
474    }
475
476    // update vseg.pbase field and update vsegs chaining
477    vseg->pbase     = ((paddr_t)ppn) << 12;
478    vseg->mapped    = 1;
479
480
481    //////////// Third step : (only if the vseg is a page table)
482    //////////// - compute the physical & virtual base address for each vspace
483    ////////////   by dividing the vseg in several sub-segments.
484    //////////// - register it in _ptabs_vaddr & _ptabs_paddr arrays,
485    ////////////   and initialize next_pt2 allocators.
486    //////////// - reset all entries in first level page tables
487   
488    if ( is_ptab )
489    {
490        unsigned int   vs;        // vspace index
491        unsigned int   nspaces;   // number of vspaces
492        unsigned int   nsp;       // number of small pages for one PTAB
493        unsigned int   offset;    // address offset for current PTAB
494
495        nspaces = header->vspaces;
496        offset  = 0;
497
498        // each PTAB must be aligned on a 8 Kbytes boundary
499        nsp = ( vseg->length >> 12 ) / nspaces;
500        if ( (nsp & 0x1) == 0x1 ) nsp = nsp - 1;
501
502        // compute max_pt2
503        _ptabs_max_pt2 = ((nsp<<12) - PT1_SIZE) / PT2_SIZE;
504
505        for ( vs = 0 ; vs < nspaces ; vs++ )
506        {
507            _ptabs_vaddr   [vs][x_dest][y_dest] = (vpn + offset) << 12;
508            _ptabs_paddr   [vs][x_dest][y_dest] = ((paddr_t)(ppn + offset)) << 12;
509            _ptabs_next_pt2[vs][x_dest][y_dest] = 0;
510            offset += nsp;
511
512            // reset all entries in PT1 (8 Kbytes)
513            _physical_memset( _ptabs_paddr[vs][x_dest][y_dest], PT1_SIZE, 0 );
514        }
515    }
516
517    asm volatile ("sync");
518
519#if BOOT_DEBUG_PT
520if ( big )
521_printf("\n[BOOT] vseg %s : cluster[%d,%d] / "
522       "vbase = %x / length = %x / BIG    / npages = %d / pbase = %l\n",
523       vseg->name, x_dest, y_dest, vseg->vbase, vseg->length, npages, vseg-> pbase );
524else
525_printf("\n[BOOT] vseg %s : cluster[%d,%d] / "
526        "vbase = %x / length = %x / SMALL / npages = %d / pbase = %l\n",
527       vseg->name, x_dest, y_dest, vseg->vbase, vseg->length, npages, vseg-> pbase );
528#endif
529
530} // end boot_vseg_map()
531
532/////////////////////////////////////////////////////////////////////////////////////
533// For the vseg defined by the vseg pointer, this function register PTEs
534// in one or several page tables.
535// It is a global vseg (kernel vseg) if (vspace_id == 0xFFFFFFFF).
536// The number of involved PTABs depends on the "local" and "global" attributes:
537//  - PTEs are replicated in all vspaces for a global vseg.
538//  - PTEs are replicated in all clusters containing procs for a non local vseg.
539/////////////////////////////////////////////////////////////////////////////////////
540void boot_vseg_pte( mapping_vseg_t*  vseg,
541                    unsigned int     vspace_id )
542{
543    // compute the "global" vseg attribute and actual vspace index
544    unsigned int        global;
545    unsigned int        vsid;   
546    if ( vspace_id == 0xFFFFFFFF )
547    {
548        global = 1;
549        vsid   = 0;
550    }
551    else
552    {
553        global = 0;
554        vsid   = vspace_id;
555    }
556
557    // compute the "local" and "big" attributes
558    unsigned int        local  = vseg->local;
559    unsigned int        big    = vseg->big;
560
561    // compute vseg flags
562    // The three flags (Local, Remote and Dirty) are set to 1
563    // to avoid hardware update for these flags, because GIET_VM
564    // does use these flags.
565    unsigned int flags = 0;
566    if (vseg->mode & C_MODE_MASK) flags |= PTE_C;
567    if (vseg->mode & X_MODE_MASK) flags |= PTE_X;
568    if (vseg->mode & W_MODE_MASK) flags |= PTE_W;
569    if (vseg->mode & U_MODE_MASK) flags |= PTE_U;
570    if ( global )                 flags |= PTE_G;
571                                  flags |= PTE_L;
572                                  flags |= PTE_R;
573                                  flags |= PTE_D;
574
575    // compute VPN, PPN and number of pages (big or small)
576    unsigned int vpn     = vseg->vbase >> 12;
577    unsigned int vpn_max = (vseg->vbase + vseg->length - 1) >> 12;
578    unsigned int ppn     = (unsigned int)(vseg->pbase >> 12);
579    unsigned int npages;
580    if ( big == 0 ) npages  = vpn_max - vpn + 1;           
581    else            npages  = (vpn_max>>9) - (vpn>>9) + 1; 
582
583    // compute destination cluster coordinates, for local vsegs
584    mapping_header_t*   header       = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
585    mapping_cluster_t*  cluster      = _get_cluster_base(header);
586    mapping_pseg_t*     pseg         = _get_pseg_base(header);
587    mapping_pseg_t*     pseg_dest    = &pseg[vseg->psegid];
588    mapping_cluster_t*  cluster_dest = &cluster[pseg_dest->clusterid];
589    unsigned int        x_dest       = cluster_dest->x;
590    unsigned int        y_dest       = cluster_dest->y;
591
592    unsigned int p;           // iterator for physical page index
593    unsigned int x;           // iterator for cluster x coordinate 
594    unsigned int y;           // iterator for cluster y coordinate 
595    unsigned int v;           // iterator for vspace index
596
597    // loop on PTEs
598    for ( p = 0 ; p < npages ; p++ )
599    { 
600        if  ( (local != 0) && (global == 0) )         // one cluster  / one vspace
601        {
602            if ( big )   // big pages => PTE1s
603            {
604                boot_add_pte1( vsid,
605                               x_dest,
606                               y_dest,
607                               vpn + (p<<9),
608                               flags, 
609                               ppn + (p<<9) );
610            }
611            else         // small pages => PTE2s
612            {
613                boot_add_pte2( vsid,
614                               x_dest,
615                               y_dest,
616                               vpn + p,     
617                               flags, 
618                               ppn + p );
619            }
620        }
621        else if ( (local == 0) && (global == 0) )     // all clusters / one vspace
622        {
623            for ( x = 0 ; x < X_SIZE ; x++ )
624            {
625                for ( y = 0 ; y < Y_SIZE ; y++ )
626                {
627                    if ( cluster[(x * Y_SIZE) + y].procs )
628                    {
629                        if ( big )   // big pages => PTE1s
630                        {
631                            boot_add_pte1( vsid,
632                                           x,
633                                           y,
634                                           vpn + (p<<9),
635                                           flags, 
636                                           ppn + (p<<9) );
637                        }
638                        else         // small pages => PTE2s
639                        {
640                            boot_add_pte2( vsid,
641                                           x,
642                                           y,
643                                           vpn + p,
644                                           flags, 
645                                           ppn + p );
646                        }
647                    }
648                }
649            }
650        }
651        else if ( (local != 0) && (global != 0) )     // one cluster  / all vspaces
652        {
653            for ( v = 0 ; v < header->vspaces ; v++ )
654            {
655                if ( big )   // big pages => PTE1s
656                {
657                    boot_add_pte1( v,
658                                   x_dest,
659                                   y_dest,
660                                   vpn + (p<<9),
661                                   flags, 
662                                   ppn + (p<<9) );
663                }
664                else         // small pages = PTE2s
665                { 
666                    boot_add_pte2( v,
667                                   x_dest,
668                                   y_dest,
669                                   vpn + p,
670                                   flags, 
671                                   ppn + p );
672                }
673            }
674        }
675        else if ( (local == 0) && (global != 0) )     // all clusters / all vspaces
676        {
677            for ( x = 0 ; x < X_SIZE ; x++ )
678            {
679                for ( y = 0 ; y < Y_SIZE ; y++ )
680                {
681                    if ( cluster[(x * Y_SIZE) + y].procs )
682                    {
683                        for ( v = 0 ; v < header->vspaces ; v++ )
684                        {
685                            if ( big )  // big pages => PTE1s
686                            {
687                                boot_add_pte1( v,
688                                               x,
689                                               y,
690                                               vpn + (p<<9),
691                                               flags, 
692                                               ppn + (p<<9) );
693                            }
694                            else        // small pages -> PTE2s
695                            {
696                                boot_add_pte2( v,
697                                               x,
698                                               y,
699                                               vpn + p,
700                                               flags, 
701                                               ppn + p );
702                            }
703                        }
704                    }
705                }
706            }
707        }
708    }  // end for pages
709
710    asm volatile ("sync");
711
712}  // end boot_vseg_pte()
713
714
715///////////////////////////////////////////////////////////////////////////////
716// This function is executed by  processor[x][y][0] in each cluster
717// containing at least one processor.
718// It initialises all page table for all global or private vsegs
719// mapped in cluster[x][y], as specified in the mapping.
720// In each cluster all page tables for the different vspaces must be
721// packed in one vseg occupying one single BPP (Big Physical Page).
722//
723// For each vseg, the mapping is done in two steps:
724// 1) mapping : the boot_vseg_map() function allocates contiguous BPPs
725//    or SPPs (if the vseg is not associated to a peripheral), and register
726//    the physical base address in the vseg pbase field. It initialises the
727//    _ptabs_vaddr[] and _ptabs_paddr[] arrays if the vseg is a PTAB.
728//
729// 2) page table initialisation : the boot_vseg_pte() function initialise
730//    the PTEs (both PTE1 and PTE2) in one or several page tables:
731//    - PTEs are replicated in all vspaces for a global vseg.
732//    - PTEs are replicated in all clusters for a non local vseg.
733//
734// We must handle vsegs in the following order
735//   1) global vseg containing PTAB mapped in cluster[x][y],
736//   2) global vsegs occupying more than one BPP mapped in cluster[x][y],
737//   3) others global vsegs mapped in cluster[x][y],
738//   4) all private vsegs in all user spaces mapped in cluster[x][y].
739///////////////////////////////////////////////////////////////////////////////
740void boot_ptab_init( unsigned int cx,
741                     unsigned int cy ) 
742{
743    mapping_header_t*   header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
744    mapping_vspace_t*   vspace = _get_vspace_base(header);
745    mapping_vseg_t*     vseg   = _get_vseg_base(header);
746    mapping_cluster_t*  cluster ;
747    mapping_pseg_t*     pseg    ;
748
749    unsigned int vspace_id;
750    unsigned int vseg_id;
751
752    unsigned int procid     = _get_procid();
753    unsigned int lpid       = procid & ((1<<P_WIDTH)-1);
754
755    if( lpid )
756    {
757        _printf("\n[BOOT ERROR] in boot_ptab_init() : "
758                "P[%d][%d][%d] should not execute it\n", cx, cy, lpid );
759        _exit();
760    } 
761
762    if ( header->vspaces == 0 )
763    {
764        _printf("\n[BOOT ERROR] in boot_ptab_init() : "
765                "mapping %s contains no vspace\n", header->name );
766        _exit();
767    }
768
769    ///////// Phase 1 : global vseg containing the PTAB (two barriers required)
770
771    // get PTAB global vseg in cluster(cx,cy)
772    unsigned int found = 0;
773    for (vseg_id = 0; vseg_id < header->globals; vseg_id++) 
774    {
775        pseg    = _get_pseg_base(header) + vseg[vseg_id].psegid;
776        cluster = _get_cluster_base(header) + pseg->clusterid;
777        if ( (vseg[vseg_id].type == VSEG_TYPE_PTAB) && 
778             (cluster->x == cx) && (cluster->y == cy) )
779        {
780            found = 1;
781            break;
782        }
783    }
784    if ( found == 0 )
785    {
786        _printf("\n[BOOT ERROR] in boot_ptab_init() : "
787                "cluster[%d][%d] contains no PTAB vseg\n", cx , cy );
788        _exit();
789    }
790
791    boot_vseg_map( &vseg[vseg_id], 0xFFFFFFFF );
792
793    //////////////////////////////////////////////
794    _simple_barrier_wait( &_barrier_all_clusters );
795    //////////////////////////////////////////////
796
797    boot_vseg_pte( &vseg[vseg_id], 0xFFFFFFFF );
798
799    //////////////////////////////////////////////
800    _simple_barrier_wait( &_barrier_all_clusters );
801    //////////////////////////////////////////////
802
803    ///////// Phase 2 : global vsegs occupying more than one BPP
804
805    for (vseg_id = 0; vseg_id < header->globals; vseg_id++) 
806    {
807        pseg    = _get_pseg_base(header) + vseg[vseg_id].psegid;
808        cluster = _get_cluster_base(header) + pseg->clusterid;
809        if ( (vseg[vseg_id].length > 0x200000) &&
810             (vseg[vseg_id].mapped == 0) &&
811             (cluster->x == cx) && (cluster->y == cy) )
812        {
813            boot_vseg_map( &vseg[vseg_id], 0xFFFFFFFF );
814            boot_vseg_pte( &vseg[vseg_id], 0xFFFFFFFF );
815        }
816    }
817
818    ///////// Phase 3 : all others global vsegs
819
820    for (vseg_id = 0; vseg_id < header->globals; vseg_id++) 
821    { 
822        pseg    = _get_pseg_base(header) + vseg[vseg_id].psegid;
823        cluster = _get_cluster_base(header) + pseg->clusterid;
824        if ( (vseg[vseg_id].mapped == 0) && 
825             (cluster->x == cx) && (cluster->y == cy) )
826        {
827            boot_vseg_map( &vseg[vseg_id], 0xFFFFFFFF );
828            boot_vseg_pte( &vseg[vseg_id], 0xFFFFFFFF );
829        }
830    }
831
832    ///////// Phase 4 : all private vsegs
833
834    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
835    {
836        for (vseg_id = vspace[vspace_id].vseg_offset;
837             vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs);
838             vseg_id++) 
839        {
840            pseg    = _get_pseg_base(header) + vseg[vseg_id].psegid;
841            cluster = _get_cluster_base(header) + pseg->clusterid;
842            if ( (cluster->x == cx) && (cluster->y == cy) )
843            {
844                boot_vseg_map( &vseg[vseg_id], vspace_id );
845                boot_vseg_pte( &vseg[vseg_id], vspace_id );
846            }
847        }
848    }
849
850    //////////////////////////////////////////////
851    _simple_barrier_wait( &_barrier_all_clusters );
852    //////////////////////////////////////////////
853
854} // end boot_ptab_init()
855
856////////////////////////////////////////////////////////////////////////////////
857// This function should be executed by P[0][0][0] only. It complete the
858// page table initialisation, taking care of all global vsegs that are
859// not mapped in a cluster containing a processor, and have not been
860// handled by the boot_ptab_init(x,y) function.
861// An example of such vsegs are the external peripherals in TSAR_LETI platform.
862////////////////////////////////////////////////////////////////////////////////
863void boot_ptab_extend()
864{
865
866    mapping_header_t*   header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
867    mapping_vseg_t*     vseg   = _get_vseg_base(header);
868
869    unsigned int vseg_id;
870
871    for (vseg_id = 0; vseg_id < header->globals; vseg_id++) 
872    {
873        if ( vseg[vseg_id].mapped == 0 ) 
874        {
875            boot_vseg_map( &vseg[vseg_id], 0xFFFFFFFF );
876            boot_vseg_pte( &vseg[vseg_id], 0xFFFFFFFF );
877        }
878    }
879}  // end boot_ptab_extend()
880
881///////////////////////////////////////////////////////////////////////////////
882// This function returns in the vbase and length buffers the virtual base
883// address and the length of the  segment allocated to the schedulers array
884// in the cluster defined by the clusterid argument.
885///////////////////////////////////////////////////////////////////////////////
886void boot_get_sched_vaddr( unsigned int  cluster_id,
887                           unsigned int* vbase, 
888                           unsigned int* length )
889{
890    mapping_header_t* header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
891    mapping_vseg_t*   vseg   = _get_vseg_base(header);
892    mapping_pseg_t*   pseg   = _get_pseg_base(header);
893
894    unsigned int vseg_id;
895    unsigned int found = 0;
896
897    for ( vseg_id = 0 ; (vseg_id < header->vsegs) && (found == 0) ; vseg_id++ )
898    {
899        if ( (vseg[vseg_id].type == VSEG_TYPE_SCHED) && 
900             (pseg[vseg[vseg_id].psegid].clusterid == cluster_id ) )
901        {
902            *vbase  = vseg[vseg_id].vbase;
903            *length = vseg[vseg_id].length;
904            found = 1;
905        }
906    }
907    if ( found == 0 )
908    {
909        mapping_cluster_t* cluster = _get_cluster_base(header);
910        _printf("\n[BOOT ERROR] No vseg of type SCHED in cluster [%d,%d]\n",
911                cluster[cluster_id].x, cluster[cluster_id].y );
912        _exit();
913    }
914} // end boot_get_sched_vaddr()
915
916#if BOOT_DEBUG_SCHED
917/////////////////////////////////////////////////////////////////////////////
918// This debug function should be executed by only one procesor.
919// It loops on all processors in all clusters to display
920// the HWI / PTI / WTI interrupt vectors for each processor.
921/////////////////////////////////////////////////////////////////////////////
922void boot_sched_irq_display()
923{
924    unsigned int         cx;
925    unsigned int         cy;
926    unsigned int         lpid;
927    unsigned int         slot;
928    unsigned int         entry;
929
930    mapping_header_t*    header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
931    mapping_cluster_t*   cluster = _get_cluster_base(header);
932
933    static_scheduler_t*  psched; 
934
935    for ( cx = 0 ; cx < X_SIZE ; cx++ )
936    {
937        for ( cy = 0 ; cy < Y_SIZE ; cy++ )
938        {
939            unsigned int cluster_id = (cx * Y_SIZE) + cy;
940            unsigned int nprocs = cluster[cluster_id].procs;
941
942            for ( lpid = 0 ; lpid < nprocs ; lpid++ )
943            {
944                psched = _schedulers[cx][cy][lpid];
945       
946                _printf("\n[BOOT] scheduler for proc[%d,%d,%d]\n",
947                        cx , cy , lpid );
948
949                for ( slot = 0 ; slot < 32 ; slot++ )
950                {
951                    entry = psched->hwi_vector[slot];
952                    if ( (entry & 0xFFFF) != 0 )     
953                    _printf(" - HWI %d / isrtype = %d / channel = %d\n",
954                            slot , (entry & 0xFFFF) , ((entry >> 16) & 0x7FFF) );
955                }
956                for ( slot = 0 ; slot < 32 ; slot++ )
957                {
958                    entry = psched->wti_vector[slot];
959                    if ( (entry & 0xFFFF) != 0 )     
960                    _printf(" - WTI %d / isrtype = %d / channel = %d\n",
961                            slot , (entry & 0xFFFF) , ((entry >> 16) & 0x7FFF) );
962                }
963                for ( slot = 0 ; slot < 32 ; slot++ )
964                {
965                    entry = psched->pti_vector[slot];
966                    if ( (entry & 0xFFFF) != 0 )     
967                    _printf(" - PTI %d / isrtype = %d / channel = %d\n",
968                            slot , (entry & 0xFFFF) , ((entry >> 16) & 0x7FFF) );
969                }
970            }
971        }
972    } 
973}  // end boot_sched_irq_display()
974#endif
975
976
977////////////////////////////////////////////////////////////////////////////////////
978// This function is executed in parallel by all processors P[x][y][0].
979// It initialises all schedulers in cluster [x][y]. The MMU must be activated.
980// It is split in two phases separated by a synchronisation barrier.
981// - In Step 1, it initialises the _schedulers[x][y][l] pointers array, the
982//              idle_task context, the  HWI / PTI / WTI interrupt vectors,
983//              and the CU HWI / PTI / WTI masks.
984// - In Step 2, it scan all tasks in all vspaces to complete the tasks contexts,
985//              initialisation as specified in the mapping_info data structure,
986//              and set the CP0_SCHED register.
987////////////////////////////////////////////////////////////////////////////////////
988void boot_scheduler_init( unsigned int x, 
989                          unsigned int y )
990{
991    mapping_header_t*    header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
992    mapping_cluster_t*   cluster = _get_cluster_base(header);
993    mapping_vspace_t*    vspace  = _get_vspace_base(header);
994    mapping_vseg_t*      vseg    = _get_vseg_base(header);
995    mapping_task_t*      task    = _get_task_base(header);
996    mapping_periph_t*    periph  = _get_periph_base(header);
997    mapping_irq_t*       irq     = _get_irq_base(header);
998
999    unsigned int         periph_id; 
1000    unsigned int         irq_id;
1001    unsigned int         vspace_id;
1002    unsigned int         vseg_id;
1003    unsigned int         task_id; 
1004
1005    unsigned int         sched_vbase;          // schedulers array vbase address
1006    unsigned int         sched_length;         // schedulers array length
1007    static_scheduler_t*  psched;               // pointer on processor scheduler
1008
1009    unsigned int cluster_id = (x * Y_SIZE) + y;
1010    unsigned int cluster_xy = (x << Y_WIDTH) + y; 
1011    unsigned int nprocs = cluster[cluster_id].procs;
1012    unsigned int lpid;                       
1013   
1014    if ( nprocs > 8 )
1015    {
1016        _printf("\n[BOOT ERROR] cluster[%d,%d] contains more than 8 procs\n", x, y );
1017        _exit();
1018    }
1019
1020    ////////////////////////////////////////////////////////////////////////////////
1021    // Step 1 : - initialize the schedulers[] array of pointers,
1022    //          - initialize the "tasks" and "current variables.
1023    //          - initialise the idle task context.
1024    //          - initialize the HWI, PTI and WTI interrupt vectors.
1025    //          - initialize the XCU masks for HWI / WTI / PTI interrupts.
1026    //
1027    // The general policy for interrupts routing is the following:         
1028    //          - the local HWI are statically allocatedted to local processors.
1029    //          - the nprocs first PTI are allocated for TICK (one per processor).
1030    //          - we allocate 4 WTI per processor: the first one is for WAKUP,
1031    //            the 3 others WTI are used for external interrupts (from PIC),
1032    //            and are dynamically allocated by kernel on demand.
1033    ///////////////////////////////////////////////////////////////////////////////
1034
1035    // get scheduler array virtual base address in cluster[x,y]
1036    boot_get_sched_vaddr( cluster_id, &sched_vbase, &sched_length );
1037
1038    if ( sched_length < (nprocs<<13) ) // 8 Kbytes per scheduler
1039    {
1040        _printf("\n[BOOT ERROR] Sched segment too small in cluster[%d,%d]\n",
1041                x, y );
1042        _exit();
1043    }
1044
1045    // loop on local processors
1046    for ( lpid = 0 ; lpid < nprocs ; lpid++ )
1047    {
1048        // get scheduler pointer and initialise the schedulers pointers array
1049        psched = (static_scheduler_t*)(sched_vbase + (lpid<<13));
1050        _schedulers[x][y][lpid] = psched;
1051
1052        // initialise the "tasks" and "current" variables default values
1053        psched->tasks   = 0;
1054        psched->current = IDLE_TASK_INDEX;
1055
1056        // set default values for HWI / PTI / SWI vectors (valid bit = 0)
1057        unsigned int slot;
1058        for (slot = 0; slot < 32; slot++)
1059        {
1060            psched->hwi_vector[slot] = 0;
1061            psched->pti_vector[slot] = 0;
1062            psched->wti_vector[slot] = 0;
1063        }
1064
1065        // initializes the idle_task context:
1066        // - the SR slot is 0xFF03 because this task run in kernel mode.
1067        // - it uses the page table of vspace[0]
1068        // - it uses the kernel TTY terminal
1069        // - slots containing addresses (SP,RA,EPC) are initialised by kernel_init()
1070
1071        psched->context[IDLE_TASK_INDEX][CTX_CR_ID]   = 0;
1072        psched->context[IDLE_TASK_INDEX][CTX_SR_ID]   = 0xFF03;
1073        psched->context[IDLE_TASK_INDEX][CTX_PTPR_ID] = _ptabs_paddr[0][x][y]>>13;
1074        psched->context[IDLE_TASK_INDEX][CTX_PTAB_ID] = _ptabs_vaddr[0][x][y];
1075        psched->context[IDLE_TASK_INDEX][CTX_TTY_ID]  = 0;
1076        psched->context[IDLE_TASK_INDEX][CTX_LTID_ID] = IDLE_TASK_INDEX;
1077        psched->context[IDLE_TASK_INDEX][CTX_VSID_ID] = 0;
1078        psched->context[IDLE_TASK_INDEX][CTX_RUN_ID]  = 1;
1079    }
1080
1081    // HWI / PTI / WTI masks (up to 8 local processors)
1082    unsigned int hwi_mask[8] = {0,0,0,0,0,0,0,0};
1083    unsigned int pti_mask[8] = {0,0,0,0,0,0,0,0};
1084    unsigned int wti_mask[8] = {0,0,0,0,0,0,0,0};
1085
1086    // scan local peripherals to get and check local XCU
1087    mapping_periph_t*  xcu = NULL;
1088    unsigned int       min = cluster[cluster_id].periph_offset ;
1089    unsigned int       max = min + cluster[cluster_id].periphs ;
1090
1091    for ( periph_id = min ; periph_id < max ; periph_id++ )
1092    {
1093        if( periph[periph_id].type == PERIPH_TYPE_XCU ) 
1094        {
1095            xcu = &periph[periph_id];
1096
1097            // check nb_hwi_in
1098            if ( xcu->arg0 < xcu->irqs )
1099            {
1100                _printf("\n[BOOT ERROR] Not enough HWI inputs for XCU[%d,%d]\n",
1101                         x, y );
1102                _exit();
1103            }
1104            // check nb_pti_in
1105            if ( xcu->arg2 < nprocs )
1106            {
1107                _printf("\n[BOOT ERROR] Not enough PTI inputs for XCU[%d,%d]\n",
1108                         x, y );
1109                _exit();
1110            }
1111            // check nb_wti_in
1112            if ( xcu->arg1 < (4 * nprocs) )
1113            {
1114                _printf("\n[BOOT ERROR] Not enough WTI inputs for XCU[%d,%d]\n",
1115                        x, y );
1116                _exit();
1117            }
1118            // check nb_irq_out
1119            if ( xcu->arg3 < (nprocs * header->irq_per_proc) )
1120            {
1121                _printf("\n[BOOT ERROR] Not enough outputs for XCU[%d,%d]\n",
1122                        x, y );
1123                _exit();
1124            }
1125        }
1126    } 
1127
1128    if ( xcu == NULL )
1129    {         
1130        _printf("\n[BOOT ERROR] missing XCU in cluster[%d,%d]\n", x , y );
1131        _exit();
1132    }
1133
1134    // HWI interrupt vector definition
1135    // scan HWI connected to local XCU
1136    // for round-robin allocation to local processors
1137    lpid = 0;
1138    for ( irq_id = xcu->irq_offset ;
1139          irq_id < xcu->irq_offset + xcu->irqs ;
1140          irq_id++ )
1141    {
1142        unsigned int type    = irq[irq_id].srctype;
1143        unsigned int srcid   = irq[irq_id].srcid;
1144        unsigned int isr     = irq[irq_id].isr & 0xFFFF;
1145        unsigned int channel = irq[irq_id].channel << 16;
1146
1147        if ( (type != IRQ_TYPE_HWI) || (srcid > 31) )
1148        {
1149            _printf("\n[BOOT ERROR] Bad IRQ in cluster[%d,%d]\n", x, y );
1150            _exit();
1151        }
1152
1153        // register entry in HWI interrupt vector
1154        _schedulers[x][y][lpid]->hwi_vector[srcid] = isr | channel;
1155
1156        // update XCU HWI mask for P[x,y,lpid]
1157        hwi_mask[lpid] = hwi_mask[lpid] | (1<<srcid);
1158
1159        lpid = (lpid + 1) % nprocs; 
1160    } // end for irqs
1161
1162    // PTI interrupt vector definition
1163    // one PTI for TICK per processor
1164    for ( lpid = 0 ; lpid < nprocs ; lpid++ )
1165    {
1166        // register entry in PTI interrupt vector
1167        _schedulers[x][y][lpid]->pti_vector[lpid] = ISR_TICK;
1168
1169        // update XCU PTI mask for P[x,y,lpid]
1170        pti_mask[lpid] = pti_mask[lpid] | (1<<lpid);
1171    }
1172
1173    // WTI interrupt vector definition
1174    // 4 WTI per processor, first for WAKUP
1175    for ( lpid = 0 ; lpid < nprocs ; lpid++ )
1176    {
1177        // register WAKUP ISR in WTI interrupt vector
1178        _schedulers[x][y][lpid]->wti_vector[4*lpid] = ISR_WAKUP;
1179
1180        // update XCU WTI mask for P[x,y,lpid] (4 entries per proc)
1181        wti_mask[lpid] = wti_mask[lpid] | (0x1<<(lpid                 ));
1182        wti_mask[lpid] = wti_mask[lpid] | (0x1<<(lpid + NB_PROCS_MAX  ));
1183        wti_mask[lpid] = wti_mask[lpid] | (0x1<<(lpid + 2*NB_PROCS_MAX));
1184        wti_mask[lpid] = wti_mask[lpid] | (0x1<<(lpid + 3*NB_PROCS_MAX));
1185    }
1186
1187    // set the XCU masks for HWI / WTI / PTI interrupts
1188    for ( lpid = 0 ; lpid < nprocs ; lpid++ )
1189    {
1190        unsigned int channel = lpid * IRQ_PER_PROCESSOR; 
1191
1192        _xcu_set_mask( cluster_xy, channel, hwi_mask[lpid], IRQ_TYPE_HWI ); 
1193        _xcu_set_mask( cluster_xy, channel, wti_mask[lpid], IRQ_TYPE_WTI );
1194        _xcu_set_mask( cluster_xy, channel, pti_mask[lpid], IRQ_TYPE_PTI );
1195    }
1196
1197    //////////////////////////////////////////////
1198    _simple_barrier_wait( &_barrier_all_clusters );
1199    //////////////////////////////////////////////
1200
1201#if BOOT_DEBUG_SCHED
1202if ( cluster_xy == 0 ) boot_sched_irq_display();
1203_simple_barrier_wait( &_barrier_all_clusters );
1204#endif
1205
1206    ///////////////////////////////////////////////////////////////////////////////
1207    // Step 2 : Initialise the tasks context. The context of task placed
1208    //          on  processor P must be stored in the scheduler of P.
1209    //          This require two nested loops: loop on the tasks, and loop
1210    //          on the local processors. We complete the scheduler when the
1211    //          required placement fit one local processor.
1212    ///////////////////////////////////////////////////////////////////////////////
1213
1214    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
1215    {
1216        // We must set the PTPR depending on the vspace, because the start_vector
1217        // and the stack address are defined in virtual space.
1218        _set_mmu_ptpr( (unsigned int)(_ptabs_paddr[vspace_id][x][y] >> 13) );
1219
1220        // loop on the tasks in vspace (task_id is the global index in mapping)
1221        for (task_id = vspace[vspace_id].task_offset;
1222             task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks);
1223             task_id++) 
1224        {
1225            // get the required task placement coordinates [x,y,p]
1226            unsigned int req_x      = cluster[task[task_id].clusterid].x;
1227            unsigned int req_y      = cluster[task[task_id].clusterid].y;
1228            unsigned int req_p      = task[task_id].proclocid;                 
1229
1230            // ctx_sr : value required before an eret instruction
1231            unsigned int ctx_sr = 0x2000FF13;
1232
1233            // ctx_ptpr : page table physical base address (shifted by 13 bit)
1234            unsigned int ctx_ptpr = (_ptabs_paddr[vspace_id][req_x][req_y] >> 13);
1235
1236            // ctx_ptab : page_table virtual base address
1237            unsigned int ctx_ptab = _ptabs_vaddr[vspace_id][req_x][req_y];
1238
1239            // ctx_epc : Get the virtual address of the memory location containing
1240            // the task entry point : the start_vector is stored by GCC in the
1241            // seg_data segment, and we must wait the .elf loading to get
1242            // the entry point value...
1243            vseg_id = vspace[vspace_id].start_vseg_id;     
1244            unsigned int ctx_epc = vseg[vseg_id].vbase + (task[task_id].startid)*4;
1245
1246            // ctx_sp :  Get the vseg containing the stack
1247            vseg_id = task[task_id].stack_vseg_id;
1248            unsigned int ctx_sp = vseg[vseg_id].vbase + vseg[vseg_id].length;
1249
1250            // get vspace thread index
1251            unsigned int thread_id = task[task_id].trdid;
1252
1253            // loop on the local processors
1254            for ( lpid = 0 ; lpid < nprocs ; lpid++ )
1255            {
1256                if ( (x == req_x) && (y == req_y) && (req_p == lpid) )   // fit
1257                {
1258                    // pointer on selected scheduler
1259                    psched = _schedulers[x][y][lpid];
1260
1261                    // get local task index in scheduler
1262                    unsigned int ltid = psched->tasks;
1263
1264                    // update the "tasks" and "current" fields in scheduler:
1265                    psched->tasks   = ltid + 1;
1266                    psched->current = 0;
1267
1268                    // initializes the task context
1269                    psched->context[ltid][CTX_CR_ID]     = 0;
1270                    psched->context[ltid][CTX_SR_ID]     = ctx_sr;
1271                    psched->context[ltid][CTX_SP_ID]     = ctx_sp;
1272                    psched->context[ltid][CTX_EPC_ID]    = ctx_epc;
1273                    psched->context[ltid][CTX_PTPR_ID]   = ctx_ptpr;
1274                    psched->context[ltid][CTX_PTAB_ID]   = ctx_ptab;
1275                    psched->context[ltid][CTX_LTID_ID]   = ltid;
1276                    psched->context[ltid][CTX_GTID_ID]   = task_id;
1277                    psched->context[ltid][CTX_TRDID_ID]  = thread_id;
1278                    psched->context[ltid][CTX_VSID_ID]   = vspace_id;
1279                    psched->context[ltid][CTX_RUN_ID]    = 1;
1280
1281                    psched->context[ltid][CTX_TTY_ID]    = 0xFFFFFFFF;
1282                    psched->context[ltid][CTX_CMA_FB_ID] = 0xFFFFFFFF;
1283                    psched->context[ltid][CTX_CMA_RX_ID] = 0xFFFFFFFF;
1284                    psched->context[ltid][CTX_CMA_TX_ID] = 0xFFFFFFFF;
1285                    psched->context[ltid][CTX_NIC_RX_ID] = 0xFFFFFFFF;
1286                    psched->context[ltid][CTX_NIC_TX_ID] = 0xFFFFFFFF;
1287                    psched->context[ltid][CTX_TIM_ID]    = 0xFFFFFFFF;
1288                    psched->context[ltid][CTX_HBA_ID]    = 0xFFFFFFFF;
1289
1290#if BOOT_DEBUG_SCHED
1291_printf("\nTask %s in vspace %s allocated to P[%d,%d,%d]\n"
1292        " - ctx[LTID]  = %d\n"
1293        " - ctx[SR]    = %x\n"
1294        " - ctx[SP]    = %x\n"
1295        " - ctx[EPC]   = %x\n"
1296        " - ctx[PTPR]  = %x\n"
1297        " - ctx[PTAB]  = %x\n"
1298        " - ctx[VSID]  = %d\n"
1299        " - ctx[TRDID] = %d\n",
1300        task[task_id].name,
1301        vspace[vspace_id].name,
1302        x, y, lpid,
1303        psched->context[ltid][CTX_LTID_ID],
1304        psched->context[ltid][CTX_SR_ID],
1305        psched->context[ltid][CTX_SP_ID],
1306        psched->context[ltid][CTX_EPC_ID],
1307        psched->context[ltid][CTX_PTPR_ID],
1308        psched->context[ltid][CTX_PTAB_ID],
1309        psched->context[ltid][CTX_VSID_ID],
1310        psched->context[ltid][CTX_TRDID_ID] );
1311#endif
1312                } // end if FIT
1313            } // end for loop on local procs
1314        } // end loop on tasks
1315    } // end loop on vspaces
1316} // end boot_scheduler_init()
1317
1318
1319
1320//////////////////////////////////////////////////////////////////////////////////
1321// This function loads the map.bin file from block device.
1322//////////////////////////////////////////////////////////////////////////////////
1323void boot_mapping_init()
1324{
1325    // open file "map.bin"
1326    int fd_id = _fat_open( 0, "map.bin", 0 );    // no IRQ / no creation
1327
1328    if ( fd_id == -1 )
1329    {
1330        _printf("\n[BOOT ERROR] : map.bin file not found \n");
1331        _exit();
1332    }
1333
1334#if BOOT_DEBUG_MAPPING
1335_printf("\n[BOOT] map.bin file successfully open at cycle %d\n", 
1336        _get_proctime() );
1337#endif
1338
1339    // get "map.bin" file size (from fat) and check it
1340    unsigned int size    = _fat.fd[fd_id].file_size;
1341
1342    if ( size > SEG_BOOT_MAPPING_SIZE )
1343    {
1344        _printf("\n[BOOT ERROR] : segment too small for map.bin file\n");
1345        _exit();
1346    }
1347
1348#if BOOT_DEBUG_MAPPING
1349_printf("\n[BOOT] map.bin buf_pbase = %x / buf_size = %x / file_size = %x\n",
1350        SEG_BOOT_MAPPING_BASE , SEG_BOOT_MAPPING_SIZE , size );
1351#endif
1352
1353    // load "map.bin" file into buffer
1354    unsigned int nblocks = size >> 9;
1355    unsigned int offset  = size & 0x1FF;
1356    if ( offset ) nblocks++;
1357
1358    unsigned int ok = _fat_read( 0,        // No IRQ
1359                                 fd_id, 
1360                                 (unsigned int*)SEG_BOOT_MAPPING_BASE, 
1361                                 nblocks,       
1362                                 0 );      // offset
1363    if ( ok == -1 )
1364    {
1365        _printf("\n[BOOT ERROR] : unable to load map.bin file \n");
1366        _exit();
1367    }
1368
1369#if BOOT_DEBUG_MAPPING
1370_printf("\n[BOOT] map.bin file successfully loaded at cycle %d\n", _get_proctime() );
1371#endif
1372
1373    // check mapping signature, number of clusters, number of vspaces 
1374    mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1375    if ( (header->signature != IN_MAPPING_SIGNATURE) ||
1376         (header->x_size    != X_SIZE)               || 
1377         (header->y_size    != Y_SIZE)               ||
1378         (header->vspaces   > GIET_NB_VSPACE_MAX)    )
1379    {
1380        _printf("\n[BOOT ERROR] Illegal mapping signature: %x\n", header->signature );
1381        _exit();
1382    }
1383
1384#if BOOT_DEBUG_MAPPING
1385unsigned int  line;
1386unsigned int* pointer = (unsigned int*)SEG_BOOT_MAPPING_BASE;
1387_printf("\n[BOOT] First block of mapping\n");
1388for ( line = 0 ; line < 8 ; line++ )
1389{
1390    _printf(" | %x | %x | %x | %x | %x | %x | %x | %x |\n",
1391            *(pointer + 0),
1392            *(pointer + 1),
1393            *(pointer + 2),
1394            *(pointer + 3),
1395            *(pointer + 4),
1396            *(pointer + 5),
1397            *(pointer + 6),
1398            *(pointer + 7) );
1399
1400    pointer = pointer + 8;
1401}
1402#endif
1403
1404#if BOOT_DEBUG_MAPPING
1405_printf("\n[BOOT] map.bin file checked at cycle %d\n", _get_proctime() );
1406#endif
1407
1408    // close file "map.bin"
1409    _fat_close( fd_id );
1410   
1411} // end boot_mapping_init()
1412
1413
1414//////////////////////////////////////////////////////////////////////////////////
1415// This function load all loadable segments contained in the .elf file identified
1416// by the "pathname" argument. Some loadable segments can be copied in several
1417// clusters: same virtual address but different physical addresses. 
1418// - It open the file.
1419// - It loads the complete file in the dedicated _boot_elf_buffer.
1420// - It copies each loadable segments  at the virtual address defined in
1421//   the .elf file, making several copies if the target vseg is not local.
1422// - It closes the file.
1423// This function is supposed to be executed by all processors[x,y,0].
1424//
1425// Note: We must use physical addresses to reach the destination buffers that
1426// can be located in remote clusters. We use either a _physical_memcpy(),
1427// or a _dma_physical_copy() if DMA is available.
1428//////////////////////////////////////////////////////////////////////////////////
1429void load_one_elf_file( unsigned int is_kernel,     // kernel file if non zero
1430                        char*        pathname,
1431                        unsigned int vspace_id )    // to scan the proper vspace
1432{
1433    mapping_header_t  * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1434    mapping_vspace_t  * vspace  = _get_vspace_base(header);
1435    mapping_vseg_t    * vseg    = _get_vseg_base(header);
1436
1437    unsigned int procid = _get_procid();
1438    unsigned int cxy    = procid >> P_WIDTH;
1439    unsigned int x      = cxy >> Y_WIDTH;
1440    unsigned int y      = cxy & ((1<<Y_WIDTH)-1);
1441    unsigned int p      = procid & ((1<<P_WIDTH)-1);
1442
1443#if BOOT_DEBUG_ELF
1444_printf("\n[DEBUG BOOT_ELF] P[%d,%d,%d] enters load_one_elf_file() : %s\n",
1445        x , y , p , pathname );
1446#endif
1447
1448    Elf32_Ehdr* elf_header_ptr = NULL;  //  avoid a warning
1449
1450    int fd_id = 0;                      //  avoid a warning
1451
1452    // only P[0,0,0] load file from FAT
1453    if ( (cxy == 0) && (p == 0) )
1454    {
1455        // open .elf file
1456        fd_id = _fat_open( 0 , pathname , 0 );  // no IRQ / no creation
1457
1458        if ( fd_id < 0 )
1459        {
1460            _printf("\n[BOOT ERROR] load_one_elf_file() : %s not found\n", 
1461                    pathname );
1462            _exit();
1463        }
1464
1465        // check buffer size versus file size
1466        if ( _fat.fd[fd_id].file_size > GIET_ELF_BUFFER_SIZE )
1467        {
1468            _printf("\n[BOOT ERROR] in load_one_elf_file() : %s / size = %x "
1469                    "larger than GIET_ELF_BUFFER_SIZE = %x\n",
1470                    pathname , _fat.fd[fd_id].file_size , GIET_ELF_BUFFER_SIZE );
1471            _exit();
1472        }
1473
1474        // compute number of sectors
1475        unsigned int nbytes   = _fat.fd[fd_id].file_size;
1476        unsigned int nsectors = nbytes>>9;
1477        if( nbytes & 0x1FF) nsectors++;
1478
1479        // load file to elf buffer
1480        if( _fat_read( 0,                    // no IRQ
1481                       fd_id, 
1482                       _boot_elf_buffer,
1483                       nsectors,
1484                       0 ) != nsectors )     // offset
1485        {
1486            _printf("\n[BOOT ERROR] load_one_elf_file() : unexpected EOF for %s\n",
1487                    pathname );
1488            _exit();
1489        }
1490
1491        // Check ELF Magic Number in ELF header
1492        Elf32_Ehdr* ptr = (Elf32_Ehdr*)_boot_elf_buffer;
1493
1494        if ( (ptr->e_ident[EI_MAG0] != ELFMAG0) ||
1495             (ptr->e_ident[EI_MAG1] != ELFMAG1) ||
1496             (ptr->e_ident[EI_MAG2] != ELFMAG2) ||
1497             (ptr->e_ident[EI_MAG3] != ELFMAG3) )
1498        {
1499            _printf("\n[BOOT ERROR] load_elf() : file %s does not use ELF format\n",
1500                    pathname );
1501            _exit();
1502        }
1503
1504#if BOOT_DEBUG_ELF
1505_printf("\n[DEBUG BOOT_ELF] P[%d,%d,%d] load file %s\n", 
1506        x , y , p , pathname );
1507#endif
1508
1509    } // end if P[0,0,0]
1510
1511    //////////////////////////////////////////////
1512    _simple_barrier_wait( &_barrier_all_clusters );
1513    //////////////////////////////////////////////
1514
1515    // Each processor P[x,y,0] copy replicated segments in cluster[x,y]
1516    elf_header_ptr = (Elf32_Ehdr*)_boot_elf_buffer;
1517
1518    // get program header table pointer
1519    unsigned int offset = elf_header_ptr->e_phoff;
1520    if( offset == 0 )
1521    {
1522        _printf("\n[BOOT ERROR] load_one_elf_file() : file %s "
1523                "does not contain loadable segment\n", pathname );
1524        _exit();
1525    }
1526
1527    Elf32_Phdr* elf_pht_ptr = (Elf32_Phdr*)(_boot_elf_buffer + offset);
1528
1529    // get number of segments
1530    unsigned int nsegments   = elf_header_ptr->e_phnum;
1531
1532    // First loop on loadable segments in the .elf file
1533    unsigned int seg_id;
1534    for (seg_id = 0 ; seg_id < nsegments ; seg_id++)
1535    {
1536        if(elf_pht_ptr[seg_id].p_type == PT_LOAD)
1537        {
1538            // Get segment attributes
1539            unsigned int seg_vaddr  = elf_pht_ptr[seg_id].p_vaddr;
1540            unsigned int seg_offset = elf_pht_ptr[seg_id].p_offset;
1541            unsigned int seg_filesz = elf_pht_ptr[seg_id].p_filesz;
1542            unsigned int seg_memsz  = elf_pht_ptr[seg_id].p_memsz;
1543
1544            if( seg_memsz != seg_filesz )
1545            {
1546                _printf("\n[BOOT ERROR] load_one_elf_file() : segment at vaddr = %x\n"
1547                        " in file %s has memsize = %x / filesize = %x \n"
1548                        " check that all global variables are in data segment\n", 
1549                        seg_vaddr, pathname , seg_memsz , seg_filesz );
1550                _exit();
1551            }
1552
1553            unsigned int src_vaddr = (unsigned int)_boot_elf_buffer + seg_offset;
1554
1555            // search all vsegs matching the virtual address
1556            unsigned int vseg_first;
1557            unsigned int vseg_last;
1558            unsigned int vseg_id;
1559            unsigned int found = 0;
1560            if ( is_kernel )
1561            {
1562                vseg_first = 0;
1563                vseg_last  = header->globals;
1564            }
1565            else
1566            {
1567                vseg_first = vspace[vspace_id].vseg_offset;
1568                vseg_last  = vseg_first + vspace[vspace_id].vsegs;
1569            }
1570
1571            // Second loop on vsegs in the mapping
1572            for ( vseg_id = vseg_first ; vseg_id < vseg_last ; vseg_id++ )
1573            {
1574                if ( seg_vaddr == vseg[vseg_id].vbase )  // matching
1575                {
1576                    found = 1;
1577
1578                    // get destination buffer physical address, size, coordinates
1579                    paddr_t      seg_paddr  = vseg[vseg_id].pbase;
1580                    unsigned int seg_size   = vseg[vseg_id].length;
1581                    unsigned int extend     = (unsigned int)(seg_paddr>>32);
1582                    unsigned int cx         = extend >> Y_WIDTH;
1583                    unsigned int cy         = extend & ((1<<Y_WIDTH)-1);
1584
1585                    // check vseg size
1586                    if ( seg_size < seg_filesz )
1587                    {
1588                        _printf("\n[BOOT ERROR] in load_one_elf_file() : vseg %s "
1589                                "is to small for loadable segment %x in file %s\n",
1590                                vseg[vseg_id].name , seg_vaddr , pathname );
1591                        _exit();
1592                    }
1593
1594                    // P[x,y,0] copy the segment from boot buffer in cluster[0,0]
1595                    // to destination buffer in cluster[x,y],
1596                    if ( (cx == x) && (cy == y) )
1597                    {
1598                        if( NB_DMA_CHANNELS > 0 )
1599                        {
1600                            _dma_physical_copy( extend,    // DMA in cluster[x,y]       
1601                                                0,         // DMA channel 0
1602                                                seg_paddr,
1603                                                (paddr_t)src_vaddr, 
1604                                                seg_filesz );   
1605                        }
1606                        else
1607                        {
1608                            _physical_memcpy( seg_paddr,            // dest paddr
1609                                              (paddr_t)src_vaddr,   // source paddr
1610                                              seg_filesz );         // size
1611                        }
1612#if BOOT_DEBUG_ELF
1613_printf("\n[DEBUG BOOT_ELF] P[%d,%d,%d] copy segment %d :\n"
1614        "  vaddr = %x / size = %x / paddr = %l\n",
1615        x , y , p , seg_id , seg_vaddr , seg_memsz , seg_paddr );
1616#endif
1617                    }
1618                }
1619            }  // end for vsegs
1620
1621            // check at least one matching vseg
1622            if ( found == 0 )
1623            {
1624                _printf("\n[BOOT ERROR] in load_one_elf_file() : vseg for loadable "
1625                        "segment %x in file %s not found "
1626                        "check consistency between the .py and .ld files\n",
1627                        seg_vaddr, pathname );
1628                _exit();
1629            }
1630        }
1631    }  // end for loadable segments
1632
1633    //////////////////////////////////////////////
1634    _simple_barrier_wait( &_barrier_all_clusters );
1635    //////////////////////////////////////////////
1636
1637    // only P[0,0,0] close the file
1638    if ( (cxy == 0) && (p == 0) )
1639    {
1640        // close .elf file
1641        _fat_close( fd_id );
1642
1643        _printf("\n[BOOT] File %s loaded at cycle %d\n", 
1644                pathname , _get_proctime() );
1645    }
1646
1647} // end load_one_elf_file()
1648
1649
1650/////i////////////////////////////////////////////////////////////////////////////////
1651// This function uses the map.bin data structure to load the "kernel.elf" file
1652// as well as the various "application.elf" files into memory.
1653// - The "preloader.elf" file is not loaded, because it has been burned in the ROM.
1654// - The "boot.elf" file is not loaded, because it has been loaded by the preloader.
1655// This function scans all vsegs defined in the map.bin data structure to collect
1656// all .elf files pathnames, and calls the load_one_elf_file() for each .elf file.
1657// As the code can be replicated in several vsegs, the same code can be copied
1658// in one or several clusters by the load_one_elf_file() function.
1659//////////////////////////////////////////////////////////////////////////////////////
1660void boot_elf_load()
1661{
1662    mapping_header_t* header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1663    mapping_vspace_t* vspace = _get_vspace_base( header );
1664    mapping_vseg_t*   vseg   = _get_vseg_base( header );
1665
1666    unsigned int      vspace_id;
1667    unsigned int      vseg_id;
1668    unsigned int      found;
1669
1670    // Scan all global vsegs to find the pathname to the kernel.elf file
1671    found = 0;
1672    for( vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
1673    {
1674        if(vseg[vseg_id].type == VSEG_TYPE_ELF) 
1675        {   
1676            found = 1;
1677            break;
1678        }
1679    }
1680
1681    // We need one kernel.elf file
1682    if (found == 0)
1683    {
1684        _printf("\n[BOOT ERROR] boot_elf_load() : kernel.elf file not found\n");
1685        _exit();
1686    }
1687
1688    // Load the kernel
1689    load_one_elf_file( 1,                           // kernel file
1690                       vseg[vseg_id].binpath,       // file pathname
1691                       0 );                         // vspace 0
1692
1693    // loop on the vspaces, scanning all vsegs in the vspace,
1694    // to find the pathname of the .elf file associated to the vspace.
1695    for( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
1696    {
1697        // loop on the private vsegs
1698        unsigned int found = 0;
1699        for (vseg_id = vspace[vspace_id].vseg_offset;
1700             vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs);
1701             vseg_id++) 
1702        {
1703            if(vseg[vseg_id].type == VSEG_TYPE_ELF) 
1704            {   
1705                found = 1;
1706                break;
1707            }
1708        }
1709
1710        // We want one .elf file per vspace
1711        if (found == 0)
1712        {
1713            _printf("\n[BOOT ERROR] boot_elf_load() : "
1714                    ".elf file not found for vspace %s\n", vspace[vspace_id].name );
1715            _exit();
1716        }
1717
1718        load_one_elf_file( 0,                          // not a kernel file
1719                           vseg[vseg_id].binpath,      // file pathname
1720                           vspace_id );                // vspace index
1721
1722    }  // end for vspaces
1723
1724} // end boot_elf_load()
1725
1726////////////////////////////////////////////////////////////////////////////////
1727// This function intializes the external peripherals in cluster_io.
1728////////////////////////////////////////////////////////////////////////////////
1729void boot_peripherals_init() 
1730{
1731    mapping_header_t * header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1732    mapping_cluster_t * cluster = _get_cluster_base(header);
1733    mapping_periph_t * periph   = _get_periph_base(header);
1734
1735    unsigned int periph_id;
1736    unsigned int channel_id;
1737
1738#if BOOT_DEBUG_PERI
1739_printf("\n[BOOT] External peripherals initialisation in cluster[%d,%d]\n",
1740        X_IO , Y_IO );
1741#endif
1742
1743    // get pointer on cluster_io
1744    mapping_cluster_t * cluster_io = &cluster[X_IO * Y_SIZE + Y_IO];
1745
1746    // loop on peripherals
1747    for (periph_id = cluster_io->periph_offset;
1748         periph_id < cluster_io->periph_offset + cluster_io->periphs; 
1749         periph_id++) 
1750    {
1751        unsigned int type       = periph[periph_id].type;
1752        unsigned int subtype    = periph[periph_id].subtype;
1753        unsigned int channels   = periph[periph_id].channels;
1754
1755        switch (type) 
1756        {
1757            case PERIPH_TYPE_IOC:    // vci_block_device component
1758            {
1759                if      ( subtype == IOC_SUBTYPE_BDV ) _bdv_init();
1760                else if ( subtype == IOC_SUBTYPE_HBA ) _hba_init();
1761                else if ( subtype == IOC_SUBTYPE_SPI ) _sdc_init();
1762                break;
1763            }
1764            case PERIPH_TYPE_TTY:    // vci_multi_tty component
1765            {
1766                for (channel_id = 0; channel_id < channels; channel_id++) 
1767                {
1768                    _tty_init( channel_id );
1769                }
1770                break;
1771            }
1772            case PERIPH_TYPE_NIC:    // vci_multi_nic component
1773            {
1774                _nic_global_init( 1,      // broadcast accepted
1775                                  1,      // bypass activated
1776                                  0,      // tdm non activated
1777                                  0 );    // tdm period
1778                break;
1779            }
1780            case PERIPH_TYPE_IOB:    // vci_io_bridge component
1781            {
1782                if (GIET_USE_IOMMU) 
1783                {
1784                    // TODO
1785                    // get the iommu page table physical address
1786                    // set IOMMU page table address
1787                    // pseg_base[IOB_IOMMU_PTPR] = ptab_pbase;   
1788                    // activate IOMMU
1789                    // pseg_base[IOB_IOMMU_ACTIVE] = 1;       
1790                }
1791                break;
1792            }
1793        }  // end switch periph type
1794    } // end loop on peripherals
1795} // end boot_peripherals_init()
1796
1797/////////////////////////////////////////////////////////////////////////////////
1798// This function is executed in parallel by all processors[x][y][0].
1799// It initialises the physical memory allocator in each cluster containing
1800// a RAM pseg.
1801/////////////////////////////////////////////////////////////////////////////////
1802void boot_pmem_init( unsigned int cx,
1803                     unsigned int cy ) 
1804{
1805    mapping_header_t*  header     = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1806    mapping_cluster_t* cluster    = _get_cluster_base(header);
1807    mapping_pseg_t*    pseg       = _get_pseg_base(header);
1808
1809    unsigned int pseg_id;
1810    unsigned int procid     = _get_procid();
1811    unsigned int lpid       = procid & ((1<<P_WIDTH)-1);
1812
1813    if( lpid )
1814    {
1815        _printf("\n[BOOT ERROR] boot_pmem_init() : "
1816        "P[%d][%d][%d] should not execute it\n", cx, cy, lpid );
1817        _exit();
1818    }   
1819
1820    // scan the psegs in local cluster to find  pseg of type RAM
1821    unsigned int found      = 0;
1822    unsigned int cluster_id = cx * Y_SIZE + cy;
1823    unsigned int pseg_min   = cluster[cluster_id].pseg_offset;
1824    unsigned int pseg_max   = pseg_min + cluster[cluster_id].psegs;
1825    for ( pseg_id = pseg_min ; pseg_id < pseg_max ; pseg_id++ )
1826    {
1827        if ( pseg[pseg_id].type == PSEG_TYPE_RAM )
1828        {
1829            unsigned int base = (unsigned int)pseg[pseg_id].base;
1830            unsigned int size = (unsigned int)pseg[pseg_id].length;
1831            _pmem_alloc_init( cx, cy, base, size );
1832            found = 1;
1833
1834#if BOOT_DEBUG_PT
1835_printf("\n[BOOT] pmem allocator initialised in cluster[%d][%d]"
1836        " : base = %x / size = %x\n", cx , cy , base , size );
1837#endif
1838            break;
1839        }
1840    }
1841
1842    if ( found == 0 )
1843    {
1844        _printf("\n[BOOT ERROR] boot_pmem_init() : no RAM in cluster[%d][%d]\n",
1845                cx , cy );
1846        _exit();
1847    }   
1848} // end boot_pmem_init()
1849 
1850/////////////////////////////////////////////////////////////////////////
1851// This function is the entry point of the boot code for all processors.
1852/////////////////////////////////////////////////////////////////////////
1853void boot_init() 
1854{
1855
1856    unsigned int       gpid       = _get_procid();
1857    unsigned int       cx         = gpid >> (Y_WIDTH + P_WIDTH);
1858    unsigned int       cy         = (gpid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
1859    unsigned int       lpid       = gpid & ((1 << P_WIDTH) -1);
1860
1861    //////////////////////////////////////////////////////////
1862    // Phase ONE : only P[0][0][0] execute it
1863    //////////////////////////////////////////////////////////
1864    if ( gpid == 0 )   
1865    {
1866        unsigned int cid;  // index for loops
1867
1868        // initialises the TTY0 spin lock
1869        _spin_lock_init( &_tty0_spin_lock );
1870
1871        _printf("\n[BOOT] P[0,0,0] starts at cycle %d\n", _get_proctime() );
1872
1873        // initialises the FAT
1874        _fat_init( 0 );   // no IRQ
1875
1876        _printf("\n[BOOT] FAT initialised at cycle %d\n", _get_proctime() );
1877
1878        // Load the map.bin file into memory
1879        boot_mapping_init();
1880
1881        mapping_header_t*  header     = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1882        mapping_cluster_t* cluster    = _get_cluster_base(header);
1883
1884        _printf("\n[BOOT] Mapping %s loaded at cycle %d\n",
1885                header->name , _get_proctime() );
1886
1887        // initialises the barrier for all clusters containing processors
1888        unsigned int nclusters = 0;
1889        for ( cid = 0 ; cid < X_SIZE*Y_SIZE ; cid++ )
1890        {
1891            if ( cluster[cid].procs ) nclusters++ ;
1892        } 
1893
1894        _simple_barrier_init( &_barrier_all_clusters , nclusters );
1895
1896        // wake up all processors P[x][y][0]
1897        for ( cid = 1 ; cid < X_SIZE*Y_SIZE ; cid++ ) 
1898        {
1899            unsigned int x          = cluster[cid].x;
1900            unsigned int y          = cluster[cid].y;
1901            unsigned int cluster_xy = (x << Y_WIDTH) + y;
1902
1903            if ( cluster[cid].procs ) 
1904            {
1905                unsigned long long paddr = (((unsigned long long)cluster_xy)<<32) +
1906                                           SEG_XCU_BASE+XCU_REG( XCU_WTI_REG , 0 );
1907
1908                _physical_write( paddr , (unsigned int)boot_entry );
1909            }
1910        }
1911
1912        _printf("\n[BOOT] Processors P[x,y,0] start at cycle %d\n",
1913                _get_proctime() );
1914    }
1915
1916    /////////////////////////////////////////////////////////////////
1917    // Phase TWO : All processors P[x][y][0] execute it in parallel
1918    /////////////////////////////////////////////////////////////////
1919    if( lpid == 0 )
1920    {
1921        // Initializes physical memory allocator in cluster[cx][cy]
1922        boot_pmem_init( cx , cy );
1923
1924        // Build page table in cluster[cx][cy]
1925        boot_ptab_init( cx , cy );
1926
1927        //////////////////////////////////////////////
1928        _simple_barrier_wait( &_barrier_all_clusters );
1929        //////////////////////////////////////////////
1930
1931        // P[0][0][0] complete page tables with vsegs
1932        // mapped in clusters without processors
1933        if ( gpid == 0 )   
1934        {
1935            // complete page tables initialisation
1936            boot_ptab_extend();
1937
1938            _printf("\n[BOOT] Physical memory allocators and page tables"
1939                    " initialized at cycle %d\n", _get_proctime() );
1940        }
1941
1942        //////////////////////////////////////////////
1943        _simple_barrier_wait( &_barrier_all_clusters );
1944        //////////////////////////////////////////////
1945
1946        // All processors P[x,y,0] activate MMU (using local PTAB)
1947        _set_mmu_ptpr( (unsigned int)(_ptabs_paddr[0][cx][cy]>>13) );
1948        _set_mmu_mode( 0xF );
1949       
1950        // Each processor P[x,y,0] initialises all schedulers in cluster[x,y]
1951        boot_scheduler_init( cx , cy );
1952
1953        // Each processor P[x][y][0] initialises its CP0_SCHED register
1954        _set_sched( (unsigned int)_schedulers[cx][cy][0] );
1955
1956        //////////////////////////////////////////////
1957        _simple_barrier_wait( &_barrier_all_clusters );
1958        //////////////////////////////////////////////
1959
1960        if ( gpid == 0 ) 
1961        {
1962            _printf("\n[BOOT] Schedulers initialised at cycle %d\n", 
1963                    _get_proctime() );
1964        }
1965
1966       
1967        // Each processor P[x,y,0] contributes to load .elf files.
1968        boot_elf_load();
1969
1970        //////////////////////////////////////////////
1971        _simple_barrier_wait( &_barrier_all_clusters );
1972        //////////////////////////////////////////////
1973       
1974        // Processor P[0,0,0] initialises external peripherals
1975        if ( gpid == 0 ) 
1976        {
1977            // initialize external peripherals
1978            boot_peripherals_init();
1979       
1980            _printf("\n[BOOT] Peripherals initialised at cycle %d\n", 
1981                    _get_proctime() );
1982        }
1983
1984        //////////////////////////////////////////////
1985        _simple_barrier_wait( &_barrier_all_clusters );
1986        //////////////////////////////////////////////
1987
1988        // each processor P[x][y][0] wake up other processors in same cluster
1989        mapping_header_t*  header     = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1990        mapping_cluster_t* cluster    = _get_cluster_base(header);
1991        unsigned int       cluster_xy = (cx << Y_WIDTH) + cy;
1992        unsigned int       cluster_id = (cx * Y_SIZE) + cy;
1993        unsigned int p;
1994        for ( p = 1 ; p < cluster[cluster_id].procs ; p++ )
1995        {
1996            _xcu_send_wti( cluster_xy , p , (unsigned int)boot_entry );
1997        }
1998
1999        // only P[0][0][0] makes display
2000        if ( gpid == 0 )
2001        {   
2002            _printf("\n[BOOT] All processors start at cycle %d\n",
2003                    _get_proctime() );
2004        }
2005    }
2006    // Other processors than P[x][y][0] activate MMU (using local PTAB)
2007    if ( lpid != 0 )
2008    {
2009        _set_mmu_ptpr( (unsigned int)(_ptabs_paddr[0][cx][cy]>>13) );
2010        _set_mmu_mode( 0xF );
2011    }
2012
2013    // All processors set CP0_SCHED register
2014    _set_sched( (unsigned int)_schedulers[cx][cy][lpid] );
2015
2016    // All processors reset BEV bit in SR to use GIET_VM exception handler
2017    _set_sr( 0 );
2018
2019    // Each proocessor get kernel entry virtual address
2020    unsigned int kernel_entry = (unsigned int)&kernel_init_vbase;
2021
2022#if BOOT_DEBUG_ELF
2023_printf("\n@@@ P[%d,%d,%d] exit boot / jumping to %x at cycle %d\n",
2024        cx, cy, lpid, kernel_entry , _get_proctime() );
2025#endif
2026
2027    // All processors jump to kernel_init
2028    asm volatile( "jr   %0" ::"r"(kernel_entry) );
2029
2030} // end boot_init()
2031
2032
2033// Local Variables:
2034// tab-width: 4
2035// c-basic-offset: 4
2036// c-file-offsets:((innamespace . 0)(inline-open . 0))
2037// indent-tabs-mode: nil
2038// End:
2039// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
2040
Note: See TracBrowser for help on using the repository browser.