source: soft/giet_vm/sys/boot_handler.c @ 158

Last change on this file since 158 was 158, checked in by alain, 12 years ago

Introducing the giet_vm and some example applications

File size: 45.4 KB
Line 
1//////////////////////////////////////////////////////////////////////////////////
2// File     : boot_handler.c
3// Date     : 01/04/2012
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// The boot_handler.h and boot_handler.c files are part of the GIET nano-kernel.
8// This code can be used in the boot phase to launch one or several multi-tasks
9// applications on a many_cores hardware architecture.
10// It uses the SoCLib generic MMU (paged virtual memory) to provide two services:
11//
12// 1) classical memory protection, when several independant applications compiled
13//    in different virtual spaces are executing on the same hardware platform.
14// 2) data placement in NUMA architectures, when we want to control the placement
15//    of the software objects (virtual segments) on the physical memory banks.
16//
17// It uses the MAPPING_INFO binary data structures, that must be pre-loaded in the
18// boot ROM in the seg_boot_mapping segment (at address seg_boot_mapping_base).
19// This MAPPING_INFO data structure defines both the hardware architecture,
20// and the mapping:
21// - number of clusters,
22// - number of processors in each cluster,
23// - physical segmentation of the physical address space,
24// - number of virtual spaces (one multi-task application per vspace),
25// - number of tasks per vspace,
26// - number of mwmr channels per vspace,
27// - number of virtual segments per vspace,
28// - static placement of tasks on the processors,
29// - static placement of virtual segments (vseg) in the physical segments (pseg).
30//
31// The page table are statically constructed in the boot phase, and they do not
32// change during execution. The GIET uses only 4 Kbytes pages.
33// As most applications use only a limited number of segments, the number of PT2s
34// actually used by a given virtual space is generally smaller than 2048, and is
35// defined at compile time (GIET_NB_PT2_MAX configuration parameter).
36// For alignment constraints, GIET_NB_PT2_MAX must be an even number.
37// The max number of virtual spaces (GIET_NB_VSPACE_MAX) is a configuration parameter.
38//
39// Each page table (one page table per virtual space) is monolithic:
40// - a first 8K aligned PT1[2148] array, indexed by the (ix1) field of VPN.
41//   The PT1 contains 2048 PTD of 4 bytes => 8K bytes.
42// - an aray of array PT2[1024][GIET_NB_PT2_MAX], indexed by
43//   the (ix2) field of the VPN, and by the PT2 index (pt2_id).
44//   Each PT2 contains 512 PTE2 of 8bytes => 4Kbytes * GIET_NB_PT2_MAX
45// The size of each page table is 8K + (GIET_NB_PT2_MAX)*4K bytes.
46// All page tables must be stored in the seg_kernel_pt segment (at address
47// seg_kernel_pt_base)
48////////////////////////////////////////////////////////////////////////////////////
49
50#include <mips32_registers.h>
51#include <boot_handler.h>
52#include <mapping_info.h>
53#include <giet_config.h>
54#include <common.h>
55#include <ctx_handler.h>
56#include <irq_handler.h>
57#include <hwr_mapping.h>
58#include <mwmr.h>
59
60#define in_ptab __attribute__((section (".ptab")))
61#define in_boot __attribute__((section (".boot")))
62
63#if !defined(GIET_NB_VSPACE_MAX)
64# error The GIET_NB_VSPACE_MAX value must be defined in the 'giet_config.h' file !
65#endif
66
67#if !defined(GIET_NB_PT2_MAX)
68# error The GIET_NB_PT2_MAX value must be defined in the 'giet_config.h' file !
69#endif
70
71////////////////////////////////////////////////////////////////////////////
72//  Global variables
73////////////////////////////////////////////////////////////////////////////
74
75// Page Tables (each one takes PT1_SIZE + (GIET_NB_PT2_MAX)*PT2_SIZE bytes
76// It will be stored in seg_kernel_pt segment
77in_ptab page_table_t      _ptab_array[GIET_NB_VSPACE_MAX];
78
79// PT2 allocator : next free PT2 index
80// will be stored in seg_kernel_data segment
81unsigned int    _next_free_pt2[GIET_NB_VSPACE_MAX] =
82                         { [0 ... GIET_NB_VSPACE_MAX-1] = 0 };
83
84
85//////////////////////////////////////////////////////////////////////////////
86// boot_procid()
87//////////////////////////////////////////////////////////////////////////////
88in_boot unsigned int boot_procid()
89{
90    unsigned int ret;
91    asm volatile("mfc0 %0, $15, 1" : "=r"(ret));
92    return (ret & 0x3FF);
93}
94
95//////////////////////////////////////////////////////////////////////////////
96// boot_time()
97//////////////////////////////////////////////////////////////////////////////
98in_boot unsigned int boot_time()
99{
100    unsigned int ret;
101    asm volatile("mfc0 %0, $9" : "=r"(ret));
102    return ret;
103}
104
105//////////////////////////////////////////////////////////////////////////////
106// boot_exit()
107//////////////////////////////////////////////////////////////////////////////
108in_boot void boot_exit()
109{
110    while(1) asm volatile("nop");
111}
112
113////////////////////////////////////////////////////////////////////////////
114//      boot_eret()
115////////////////////////////////////////////////////////////////////////////
116in_boot void boot_eret()
117{
118    asm volatile("eret");
119}
120
121////////////////////////////////////////////////////////////////////////////
122//      boot_strncmp()
123////////////////////////////////////////////////////////////////////////////
124in_boot int boot_strncmp( const char* s1, 
125                          const char* s2,
126                          unsigned int n )
127{
128    unsigned int i;
129    for ( i=0 ; i<n ; i++)
130    {
131        if ( s1[i] != s2[i] ) return 1;
132        if ( s1[i] == 0 )     break;
133    }
134    return 0;
135}
136
137////////////////////////////////////////////////////////////////////////////
138// boot_tty_puts()
139// (it uses TTY0)
140////////////////////////////////////////////////////////////////////////////
141in_boot void boot_tty_puts(const char *buffer) 
142{
143    unsigned int* tty_address = (unsigned int*)&seg_tty_base;
144    unsigned int n;
145
146    for ( n=0; n<100; n++)
147    {
148        if (buffer[n] == 0) break;
149        tty_address[0] = (unsigned int)buffer[n];
150    }
151} 
152
153////////////////////////////////////////////////////////////////////////////
154// boot_tty_putw()
155// (it uses TTY0)
156////////////////////////////////////////////////////////////////////////////
157in_boot void boot_tty_putw(unsigned int val)
158{
159    static const char   HexaTab[] = "0123456789ABCDEF";
160    char                buf[11];
161    unsigned int        c;
162
163    buf[0]  = '0';
164    buf[1]  = 'x';
165    buf[10] = 0;
166
167    for ( c = 0 ; c < 8 ; c++ )
168    { 
169        buf[9-c] = HexaTab[val&0xF];
170        val = val >> 4;
171    }
172    boot_tty_puts(buf);
173}
174
175/////////////////////////////////////////////////////////////////////////////
176// various mapping_info data structure access functions
177/////////////////////////////////////////////////////////////////////////////
178in_boot mapping_cluster_t* boot_get_cluster_base( mapping_header_t* header )
179{
180    return   (mapping_cluster_t*) ((char*)header +
181                                  MAPPING_HEADER_SIZE);
182}
183/////////////////////////////////////////////////////////////////////////////
184in_boot mapping_pseg_t* boot_get_pseg_base( mapping_header_t* header )
185{
186    return   (mapping_pseg_t*)    ((char*)header +
187                                  MAPPING_HEADER_SIZE +
188                                  MAPPING_CLUSTER_SIZE*header->clusters);
189}
190/////////////////////////////////////////////////////////////////////////////
191in_boot mapping_vspace_t* boot_get_vspace_base( mapping_header_t* header )
192{
193    return   (mapping_vspace_t*)  ((char*)header +
194                                  MAPPING_HEADER_SIZE +
195                                  MAPPING_CLUSTER_SIZE*header->clusters +
196                                  MAPPING_PSEG_SIZE*header->psegs);
197}
198/////////////////////////////////////////////////////////////////////////////
199in_boot mapping_vseg_t* boot_get_vseg_base( mapping_header_t* header )
200{
201    return   (mapping_vseg_t*)    ((char*)header +
202                                  MAPPING_HEADER_SIZE +
203                                  MAPPING_CLUSTER_SIZE*header->clusters +
204                                  MAPPING_PSEG_SIZE*header->psegs +
205                                  MAPPING_VSPACE_SIZE*header->vspaces);
206}
207/////////////////////////////////////////////////////////////////////////////
208in_boot mapping_task_t* boot_get_task_base( mapping_header_t* header )
209{
210    return   (mapping_task_t*)    ((char*)header +
211                                  MAPPING_HEADER_SIZE +
212                                  MAPPING_CLUSTER_SIZE*header->clusters +
213                                  MAPPING_PSEG_SIZE*header->psegs +
214                                  MAPPING_VSPACE_SIZE*header->vspaces +
215                                  MAPPING_VSEG_SIZE*header->vsegs);
216}
217
218/////////////////////////////////////////////////////////////////////////////
219// print the content of the mapping_info data structure
220////////////////////////////////////////////////////////////////////////
221in_boot void boot_print_mapping_info()
222{
223    mapping_header_t*   header = (mapping_header_t*)&seg_boot_mapping_base; 
224   
225    unsigned int                vspace_id;
226    unsigned int                cluster_id;
227    unsigned int                pseg_id;
228    unsigned int                vseg_id;
229    unsigned int                task_id;
230
231    mapping_cluster_t*  cluster = boot_get_cluster_base( header );
232    mapping_pseg_t*         pseg    = boot_get_pseg_base( header );;
233    mapping_vspace_t*   vspace  = boot_get_vspace_base ( header );;
234    mapping_vseg_t*         vseg    = boot_get_vseg_base ( header );
235    mapping_task_t*         task    = boot_get_task_base ( header );;
236
237    // header
238    boot_tty_puts("mapping_info");
239
240    boot_tty_puts("\n - signature = ");
241    boot_tty_putw(header->signature);
242    boot_tty_puts("\n - name      = ");
243    boot_tty_puts(header->name);
244    boot_tty_puts("\n - clusters  = ");
245    boot_tty_putw(header->clusters);
246    boot_tty_puts("\n - psegs     = ");
247    boot_tty_putw(header->psegs);
248    boot_tty_puts("\n - ttys      = ");
249    boot_tty_putw(header->ttys);
250    boot_tty_puts("\n - vspaces   = ");
251    boot_tty_putw(header->vspaces);
252    boot_tty_puts("\n - globals   = ");
253    boot_tty_putw(header->globals);
254    boot_tty_puts("\n - vsegs     = ");
255    boot_tty_putw(header->vsegs);
256    boot_tty_puts("\n - tasks     = ");
257    boot_tty_putw(header->tasks);
258    boot_tty_puts("\n - syspath   = ");
259    boot_tty_puts(header->syspath);
260    boot_tty_puts("\n\n");
261
262    // clusters
263    for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
264    {
265        boot_tty_puts("cluster ");
266        boot_tty_putw(cluster_id);
267
268        boot_tty_puts("\n - procs  = ");
269        boot_tty_putw(cluster[cluster_id].procs);
270        boot_tty_puts("\n - timers = ");
271        boot_tty_putw(cluster[cluster_id].timers);
272        boot_tty_puts("\n - dmas   = ");
273        boot_tty_putw(cluster[cluster_id].dmas);
274        boot_tty_puts("\n\n");
275    }
276
277    // psegs
278    for ( pseg_id = 0 ; pseg_id < header->psegs ; pseg_id++ )
279    {
280        boot_tty_puts("pseg ");
281        boot_tty_putw(pseg_id);
282
283        boot_tty_puts("\n - name   = ");
284        boot_tty_puts( pseg[pseg_id].name );
285        boot_tty_puts("\n - base   = ");
286        boot_tty_putw( pseg[pseg_id].base );
287        boot_tty_puts("\n - length = ");
288        boot_tty_putw( pseg[pseg_id].length );
289        boot_tty_puts("\n\n");
290    }
291
292    // globals
293    for ( vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
294    {
295        boot_tty_puts("global vseg ");
296        boot_tty_putw(vseg_id);
297
298        boot_tty_puts("\n - name   = ");
299        boot_tty_puts( vseg[vseg_id].name );
300        boot_tty_puts("\n - vbase  = ");
301        boot_tty_putw( vseg[vseg_id].vbase );
302        boot_tty_puts("\n - length = ");
303        boot_tty_putw( vseg[vseg_id].length );
304        boot_tty_puts("\n - mode   = ");
305        boot_tty_putw( vseg[vseg_id].mode );
306        boot_tty_puts("\n - ident = ");
307        boot_tty_putw( vseg[vseg_id].ident );
308        boot_tty_puts("\n - psegname = ");
309        boot_tty_puts( pseg[vseg[vseg_id].psegid].name );
310        boot_tty_puts("\n\n");
311    }
312
313    // vspaces
314    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
315    {
316        boot_tty_puts("vspace ");
317        boot_tty_putw(vspace_id);
318
319        boot_tty_puts("\n - name    = ");
320        boot_tty_puts( vspace[vspace_id].name ); 
321        boot_tty_puts("\n - binpath = ");
322        boot_tty_puts( vspace[vspace_id].binpath ); 
323        boot_tty_puts("\n - vsegs   = ");
324        boot_tty_putw( vspace[vspace_id].vsegs );
325        boot_tty_puts("\n - tasks   = ");
326        boot_tty_putw( vspace[vspace_id].tasks );
327        boot_tty_puts("\n - mwmrs   = ");
328        boot_tty_putw( vspace[vspace_id].mwmrs );
329        boot_tty_puts("\n - ttys    = ");
330        boot_tty_putw( vspace[vspace_id].ttys );
331        boot_tty_puts("\n\n");
332
333        for ( vseg_id = vspace[vspace_id].vseg_offset ; 
334              vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
335              vseg_id++ )
336        {
337            boot_tty_puts("    private vseg ");
338            boot_tty_putw( vseg_id );
339
340            boot_tty_puts("\n    - name   = ");
341            boot_tty_puts( vseg[vseg_id].name );
342            boot_tty_puts("\n    - vbase  = ");
343            boot_tty_putw( vseg[vseg_id].vbase );
344            boot_tty_puts("\n    - length = ");
345            boot_tty_putw( vseg[vseg_id].length );
346            boot_tty_puts("\n    - mode   = ");
347            boot_tty_putw( vseg[vseg_id].mode );
348            boot_tty_puts("\n    - ident = ");
349            boot_tty_putw( vseg[vseg_id].ident );
350            boot_tty_puts("\n    - psegname = ");
351            boot_tty_puts( pseg[vseg[vseg_id].psegid].name );
352            boot_tty_puts("\n\n");
353        }
354
355        for ( task_id = vspace[vspace_id].vseg_offset ; 
356              task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks) ; 
357              task_id++ )
358        {
359            boot_tty_puts("     task");
360            boot_tty_putw( task_id );
361
362            boot_tty_puts("\n     - name = ");
363            boot_tty_puts( task[task_id].name );
364            boot_tty_puts("\n     - clusterid = ");
365            boot_tty_putw( task[task_id].clusterid );
366            boot_tty_puts("\n     - proclocid = ");
367            boot_tty_putw( task[task_id].proclocid );
368            boot_tty_puts("\n     - vseglocid = ");
369            boot_tty_putw( task[task_id].vseglocid );
370            boot_tty_puts("\n     - startid   = ");
371            boot_tty_putw( task[task_id].startid );
372            boot_tty_puts("\n     - ttylocid  = ");
373            boot_tty_putw( task[task_id].ttylocid );
374            boot_tty_puts("\n\n");
375        }
376    }
377} // end boot_print_mapping_info()
378
379//////////////////////////////////////////////////////////////////////////////
380// boot_pseg_get()
381// This function returns the pointer on a physical segment
382// identified  by the segment index.
383//////////////////////////////////////////////////////////////////////////////
384in_boot mapping_pseg_t* boot_pseg_get( unsigned int seg_id)
385{
386    mapping_header_t* header = (mapping_header_t*)&seg_boot_mapping_base;
387    mapping_pseg_t*   pseg   = boot_get_pseg_base( header );
388
389    // checking argument
390    if ( seg_id >= header->psegs )
391    {
392        boot_tty_puts("\n[BOOT ERROR] : seg_id argument too large\n");
393        boot_tty_puts("               in function boot_pseg_get()\n");
394        boot_exit();
395    }
396
397    return &pseg[seg_id];                                   
398} // end boot_pseg_get()
399
400//////////////////////////////////////////////////////////////////////////////
401// boot_add_pte()
402// This function registers a new PTE in the page table pointed
403// by the vspace_id argument, and updates both PT1 and PT2.
404// A new PT2 is used when required.
405// As the set of PT2s is implemented as a fixed size array (no dynamic
406// allocation), this function checks a possible overflow of the PT2 array.
407//////////////////////////////////////////////////////////////////////////////
408in_boot void boot_add_pte( unsigned int    vspace_id,   
409                           unsigned int    vpn,           
410                           unsigned int    flags,
411                           unsigned int    ppn )
412{
413    unsigned int    ix1;
414    unsigned int    ix2;
415    unsigned int    ptba;       // PT2 base address
416    unsigned int    pt2_id;     // PT2 index
417    unsigned int*   pt_flags;   // pointer on the pte_flags = &PT2[2*ix2]   
418    unsigned int*   pt_ppn;     // pointer on the pte_ppn   = &PT2[2*ix2+1] 
419
420    ix1 = vpn >> 9;             // 11 bits
421    ix2 = vpn  & 0x1FF;         //  9 bits
422
423    // get the page table base address
424    page_table_t* pt = (page_table_t *)(&_ptab_array[vspace_id]);
425
426    if ( (pt->pt1[ix1] & PTE_V) == 0 )   // set a new PTD in PT1
427    {
428        pt2_id = _next_free_pt2[vspace_id];
429        if ( pt2_id == GIET_NB_PT2_MAX )
430        {
431            boot_tty_puts("\n[BOOT ERROR] in boot_add_pte() function\n");
432            boot_tty_puts("the GIET_NB_PT2_MAX parameter is too small\n"); 
433            boot_exit();
434        }
435        else
436        {
437            ptba = (unsigned int)pt + PT1_SIZE + PT2_SIZE*pt2_id;
438            pt->pt1[ix1] = PTE_V | PTE_T | (ptba >> 12);   
439            _next_free_pt2[vspace_id] = pt2_id + 1;
440        }
441    }
442    else
443    {
444        ptba = pt->pt1[ix1] << 12;
445    }
446
447    // set PTE2 after checking double mapping error
448    pt_flags = (unsigned int*)(ptba + 8*ix2);
449    pt_ppn   = (unsigned int*)(ptba + 8*ix2 + 4);
450
451    if ( ( *pt_flags & PTE_V) != 0 )    // page already mapped
452    {
453        boot_tty_puts("\n[BOOT ERROR] in boot_add_pte() function\n");
454        boot_tty_puts("page already mapped\n");
455        boot_exit();
456    }
457    else                                          // set PTE2
458    {
459        *pt_flags = flags;
460        *pt_ppn   = ppn;
461    }
462} // end boot_add_pte()
463               
464/////////////////////////////////////////////////////////////////////
465// This function build the page table for a given vspace.
466// The physical base addresses for all vsegs (global and private)
467// must have been previously computed.
468// It initializes the MWMR channels.
469/////////////////////////////////////////////////////////////////////
470in_boot void boot_vspace_pt_build( unsigned int vspace_id )
471{
472    unsigned int    vseg_id;
473    unsigned int    npages;
474    unsigned int    ppn;
475    unsigned int    vpn;
476    unsigned int    flags;
477    unsigned int    page_id;
478
479    mapping_header_t*  header = (mapping_header_t*)&seg_boot_mapping_base; 
480    mapping_vspace_t*  vspace = boot_get_vspace_base( header );
481    mapping_vseg_t*    vseg   = boot_get_vseg_base( header );
482
483    // global segments
484    for ( vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
485    {
486        vpn       = vseg[vseg_id].vbase >> 12;
487        ppn       = vseg[vseg_id].pbase >> 12;
488        npages    = vseg[vseg_id].length >> 12;
489        if ( (vseg[vseg_id].length & 0xFFF) != 0 ) npages++;
490
491        flags = PTE_V;
492        if ( vseg[vseg_id].mode & C_MODE_MASK )  flags = flags | PTE_C;
493        if ( vseg[vseg_id].mode & X_MODE_MASK )  flags = flags | PTE_X;
494        if ( vseg[vseg_id].mode & W_MODE_MASK )  flags = flags | PTE_W;
495        if ( vseg[vseg_id].mode & U_MODE_MASK )  flags = flags | PTE_U;
496
497#if BOOT_DEBUG_PT
498boot_tty_puts("- vseg ");
499boot_tty_puts( vseg[vseg_id].name );
500boot_tty_puts(" / flags = ");
501boot_tty_putw( flags );
502boot_tty_puts(" / npages = ");
503boot_tty_putw( npages );
504boot_tty_puts("\n");
505#endif       
506        // loop on 4K pages
507        for ( page_id = 0 ; page_id < npages ; page_id++ )
508        {
509            boot_add_pte( vspace_id,
510                          vpn,
511                          flags,
512                          ppn );
513            vpn++;
514            ppn++;
515        }
516    }
517   
518    // private segments
519    for ( vseg_id = vspace[vspace_id].vseg_offset ; 
520          vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
521          vseg_id++ )
522    {
523        vpn       = vseg[vseg_id].vbase >> 12;
524        ppn       = vseg[vseg_id].pbase >> 12;
525        npages    = vseg[vseg_id].length >> 12;
526        if ( (vseg[vseg_id].length & 0xFFF) != 0 ) npages++;
527
528        flags = PTE_V;
529        if ( vseg[vseg_id].mode & C_MODE_MASK )  flags = flags | PTE_C;
530        if ( vseg[vseg_id].mode & X_MODE_MASK )  flags = flags | PTE_X;
531        if ( vseg[vseg_id].mode & W_MODE_MASK )  flags = flags | PTE_W;
532        if ( vseg[vseg_id].mode & U_MODE_MASK )  flags = flags | PTE_U;
533
534#if BOOT_DEBUG_PT
535boot_tty_puts("- vseg ");
536boot_tty_puts( vseg[vseg_id].name );
537boot_tty_puts(" / flags = ");
538boot_tty_putw( flags );
539boot_tty_puts("\n");
540#endif       
541        // loop on 4K pages
542        for ( page_id = 0 ; page_id < npages ; page_id++ )
543        {
544            boot_add_pte( vspace_id,
545                          vpn,
546                          flags,
547                          ppn );
548            vpn++;
549            ppn++;
550        }
551
552        // initializes MWMR channel if vseg is a MWMR
553        // the channel storage capacity is (vseg.legth/4 - 5) words
554        if ( vseg[vseg_id].mwmr )
555        {
556            mwmr_channel_t* mwmr = (mwmr_channel_t*)(vseg[vseg_id].pbase);
557            mwmr->ptw   = 0;
558            mwmr->ptr   = 0;
559            mwmr->sts   = 0;
560            mwmr->depth = (vseg[vseg_id].length>>2) - 5;
561            mwmr->lock  = 0;
562
563#if BOOT_DEBUG_PT
564boot_tty_puts("   MWMR channel depth = ");
565boot_tty_putw( mwmr->depth );
566boot_tty_puts("\n");
567#endif
568
569        }
570    }
571} // end boot_vspace_pt_build()
572
573//////////////////////////////////////////////////////////////////////
574// This function uses the page tables to translate a virtual address
575// to a physical address, depending on the vspace index.
576//////////////////////////////////////////////////////////////////////
577in_boot unsigned int boot_translate( unsigned int vaddr,
578                                     unsigned int vspace_id )
579{
580    page_table_t*   ptp;
581    unsigned int*   ptba;
582    unsigned int    paddr;
583
584    // compute indexes
585    unsigned int    ix1    = (vaddr >> 21) & 0x7FF;
586    unsigned int    ix2    = (vaddr >> 12) & 0x1FF;
587    unsigned int    offset = vaddr & 0xFFF;
588   
589    // get the page table base address
590    ptp = (page_table_t*)((char*)&seg_kernel_pt_base + vspace_id*sizeof(page_table_t));
591   
592    // compute PTBA     
593    ptba = (unsigned int*)(ptp->pt1[ix1] << 12);
594
595    // compute paddr   
596    paddr = (ptba[2*ix2 + 1] << 12) + offset;
597
598#if BOOT_DEBUG_TRANSLATE
599boot_tty_puts("\nAddress Translation\n");
600boot_tty_puts("- vaddr = ");
601boot_tty_putw( vaddr );
602boot_tty_puts("\n");
603boot_tty_puts("- ix1   = ");
604boot_tty_putw( ix1 );
605boot_tty_puts("\n");
606boot_tty_puts("- ix2   = ");
607boot_tty_putw( ix2 );
608boot_tty_puts("\n");
609boot_tty_puts("- ptp   = ");
610boot_tty_putw( (unsigned int)ptp );
611boot_tty_puts("\n");
612boot_tty_puts("- ptba  = ");
613boot_tty_putw( (unsigned int)ptba );
614boot_tty_puts("\n");
615boot_tty_puts("- paddr = ");
616boot_tty_putw( paddr );
617boot_tty_puts("\n");
618#endif
619
620    return paddr;
621} // end boot_translate()
622
623///////////////////////////////////////////////////////////////////////////////
624// This function initialises the task context for a given vspace.
625// There is a private context array for each vspace, indexed by the
626// (task_id, proc_id) composite index.
627// The following values are written in the task context:
628// - SP     stack pointer = stack_base + stack_length
629// - RA     return address = &boot_eret
630// - EPC    start address = start_vector[task->startid]
631// - SR     status register = OxFF13
632// - TTY    TTY index = base_tty_id + tty_local_id
633// - PTPR   page table base address / 8K
634// - MODE   mmu_mode = 0xF (TLBs and caches activated)
635// It statically allocates the task to the proper scheduler
636// (one scheduler per processor).
637////////////////////////////////////////////////////////////////////////////////
638in_boot void boot_task_map( unsigned int        task_id,    // global index
639                            unsigned int        vspace_id,  // global index
640                            unsigned int        base_tty_id,
641                            unsigned int*       start_vector )
642{
643    mapping_header_t*   header = (mapping_header_t*)&seg_boot_mapping_base; 
644
645    mapping_vseg_t*     vseg   = boot_get_vseg_base(header);
646    mapping_task_t*     task   = boot_get_task_base(header);
647    mapping_vspace_t*   vspace = boot_get_vspace_base(header);
648
649    unsigned int        vseg_id;
650    unsigned int        loc_id;
651    unsigned int        proc_id;
652
653    unsigned int        sp;
654    unsigned int        ra   = (unsigned int)&boot_eret;
655    unsigned int        epc  = start_vector[task[task_id].startid];
656    unsigned int        tty  = base_tty_id + task[task_id].ttylocid; 
657    unsigned int        sr   = 0x0000FF13;
658    unsigned int        ptpr = ((unsigned int)&_ptab_array[vspace_id]) >> 13;
659    unsigned int        mode = 0xF;
660
661    // check values
662    if ( task[task_id].proclocid >= NB_PROCS )
663    {
664        boot_tty_puts("\n[BOOT ERROR] : processor index too large for task ");
665        boot_tty_puts( task[task_id].name );
666        boot_tty_puts(" in vspace ");
667        boot_tty_puts( vspace[vspace_id].name );
668        boot_tty_puts("\n");
669        boot_exit();
670    }
671    if ( task[task_id].clusterid >= NB_CLUSTERS )
672    {
673        boot_tty_puts("\n[BOOT ERROR] : cluster index too large for task ");
674        boot_tty_puts( task[task_id].name );
675        boot_tty_puts(" in vspace ");
676        boot_tty_puts( vspace[vspace_id].name );
677        boot_tty_puts("\n");
678        boot_exit();
679    }
680    if ( task[task_id].vseglocid >= vspace->vsegs )
681    {
682        boot_tty_puts("\n[BOOT ERROR] : vseg index too large for task ");
683        boot_tty_puts( task[task_id].name );
684        boot_tty_puts(" in vspace ");
685        boot_tty_puts( vspace[vspace_id].name );
686        boot_tty_puts("\n");
687        boot_exit();
688    }
689    if ( task[task_id].startid >= vspace->tasks )
690    {
691        boot_tty_puts("\n[BOOT ERROR] : start index too large for task ");
692        boot_tty_puts( task[task_id].name );
693        boot_tty_puts(" in vspace ");
694        boot_tty_puts( vspace[vspace_id].name );
695        boot_tty_puts("\n");
696        boot_exit();
697    }
698    if ( tty >= NB_TTYS )
699    {
700        boot_tty_puts("\n[BOOT ERROR] : TTY index too large for task ");
701        boot_tty_puts( task[task_id].name );
702        boot_tty_puts(" in vspace ");
703        boot_tty_puts( vspace[vspace_id].name );
704        boot_tty_puts("\n");
705        boot_exit();
706    }
707
708    // get stack pointer value
709    vseg_id = task[task_id].vseglocid + vspace[vspace_id].vseg_offset;
710    sp = vseg[vseg_id].vbase + vseg[vseg_id].length;
711
712    // compute global processor index
713    proc_id = task[task_id].clusterid * NB_PROCS + task[task_id].proclocid;
714
715    // check local task index
716    loc_id = _scheduler[proc_id].tasks;
717    if ( loc_id >= GIET_NB_TASKS_MAX )
718    {
719        boot_tty_puts("\n[BOOT ERROR] : too much tasks allocated to processor ");
720        boot_tty_putw( proc_id );
721        boot_tty_puts("\n");
722        boot_exit();
723    }
724   
725    // update number of tasks allocated to scheduler
726    _scheduler[proc_id].tasks = loc_id + 1;
727
728    // initializes the task context
729    _scheduler[proc_id].context[loc_id][CTX_SR_ID]   = sr;
730    _scheduler[proc_id].context[loc_id][CTX_SP_ID]   = sp;
731    _scheduler[proc_id].context[loc_id][CTX_RA_ID]   = ra;
732    _scheduler[proc_id].context[loc_id][CTX_EPC_ID]  = epc;
733    _scheduler[proc_id].context[loc_id][CTX_TTY_ID]  = tty;
734    _scheduler[proc_id].context[loc_id][CTX_PTPR_ID] = ptpr;
735    _scheduler[proc_id].context[loc_id][CTX_MODE_ID] = mode;
736   
737#if BOOT_DEBUG_CTX
738boot_tty_puts("Task ");
739boot_tty_puts( task[task_id].name );
740boot_tty_puts(" allocated to processor ");
741boot_tty_putw( proc_id );
742boot_tty_puts(" / loc_id = ");
743boot_tty_putw( loc_id );
744boot_tty_puts("\n");
745
746boot_tty_puts("  - SR          = ");
747boot_tty_putw( sr );
748boot_tty_puts("  saved at ");
749boot_tty_putw( (unsigned int)&_scheduler[proc_id].context[loc_id][CTX_SR_ID] );
750boot_tty_puts("\n");
751
752boot_tty_puts("  - RA          = ");
753boot_tty_putw( ra );
754boot_tty_puts("  saved at ");
755boot_tty_putw( (unsigned int)&_scheduler[proc_id].context[loc_id][CTX_RA_ID] );
756boot_tty_puts("\n");
757
758boot_tty_puts("  - SP          = ");
759boot_tty_putw( sp );
760boot_tty_puts("  saved at ");
761boot_tty_putw( (unsigned int)&_scheduler[proc_id].context[loc_id][CTX_SP_ID] );
762boot_tty_puts("\n");
763
764boot_tty_puts("  - EPC         = ");
765boot_tty_putw( epc );
766boot_tty_puts("  saved at ");
767boot_tty_putw( (unsigned int)&_scheduler[proc_id].context[loc_id][CTX_EPC_ID] );
768boot_tty_puts("\n");
769
770boot_tty_puts("  - TTY         = ");
771boot_tty_putw( tty );
772boot_tty_puts("  saved at ");
773boot_tty_putw( (unsigned int)&_scheduler[proc_id].context[loc_id][CTX_TTY_ID] );
774boot_tty_puts("\n");
775
776boot_tty_puts("  - PTPR        = ");
777boot_tty_putw( ptpr<<13 );
778boot_tty_puts("  saved at ");
779boot_tty_putw( (unsigned int)&_scheduler[proc_id].context[loc_id][CTX_PTPR_ID] );
780boot_tty_puts("\n");
781
782boot_tty_puts("  - MODE        = ");
783boot_tty_putw( mode );
784boot_tty_puts("  saved at ");
785boot_tty_putw( (unsigned int)&_scheduler[proc_id].context[loc_id][CTX_MODE_ID] );
786boot_tty_puts("\n");
787#endif
788
789} // end boot_task_map()
790
791///////////////////////////////////////////////////////////////////////////
792// This function compute the physical base address for a vseg
793// as specified in the mapping info data structure.
794// It updates the pbase field of the vseg.
795// It updates the page allocator (nextfreepage field of the pseg),
796// and checks a possible pseg overflow.
797///////////////////////////////////////////////////////////////////////////
798in_boot void boot_vseg_map( mapping_vseg_t* vseg ) 
799{
800    unsigned int    pages;
801
802    // check vseg alignment on 4K pages
803    if ( (vseg->vbase & 0xfff) != 0 )
804    {
805        boot_tty_puts("\n[BOOT ERROR] in boot_vseg_map() function\n");
806        boot_tty_puts("virtual segment base address not aligned: ");
807        boot_tty_puts( vseg->name );
808        boot_tty_puts("\n");
809        boot_exit();
810    }
811   
812    // computes number of pages
813    pages = vseg->length >> 12;
814    if ( (vseg->length & 0xFFF) != 0 ) pages++;
815
816    // get physical segment pointer
817    mapping_pseg_t*  pseg = boot_pseg_get( vseg->psegid );
818
819    // compute physical base address
820    if ( vseg->ident != 0 )            // identity mapping required
821    {
822        // check physical segment overflow 
823        if ( (vseg->vbase < pseg->base) || 
824             ((vseg->vbase + vseg->length) > (pseg->base + pseg->length)) )
825        {
826            boot_tty_puts("\n[BOOT ERROR] in boot_vseg_map() function\n");
827            boot_tty_puts("impossible identity mapping for virtual segment: ");
828            boot_tty_puts( vseg->name ); 
829            boot_tty_puts("\n"); 
830            boot_exit();
831        }
832        vseg->pbase = vseg->vbase;
833    }
834    else                                // unconstrained mapping
835    {
836        // check physical segment overflow
837        if ( (vseg->vbase + vseg->length) > (pseg->base + pseg->length) )
838        {
839            boot_tty_puts("\n[BOOT ERROR] in boot_vseg_map() function\n");
840            boot_tty_puts("physical segment ");
841            boot_tty_puts( pseg->name ); 
842            boot_tty_puts(" is too small to map virtual segment");
843            boot_tty_puts( vseg->name ); 
844            boot_tty_puts("\n");
845            boot_exit();
846        }
847        vseg->pbase = pseg->base + (pseg->next_free_page<<12);
848        pseg->next_free_page = pseg->next_free_page + pages;
849    }
850
851#if BOOT_DEBUG_PT
852boot_tty_puts("- vseg ");
853boot_tty_puts( vseg->name );
854boot_tty_puts(" : vbase = ");
855boot_tty_putw( vseg->vbase );
856boot_tty_puts(" / pbase = ");
857boot_tty_putw( vseg->pbase );
858boot_tty_puts("\n");
859#endif 
860
861} // end boot_vseg_map()
862
863/////////////////////////////////////////////////////////////////////
864// This function cheks the mapping_info data structure
865/////////////////////////////////////////////////////////////////////
866in_boot void boot_check_mapping()
867{
868    mapping_header_t*   header = (mapping_header_t*)&seg_boot_mapping_base; 
869
870    // checking mapping availability
871    if ( header->signature != IN_MAPPING_SIGNATURE )
872    {
873        boot_tty_puts("\n[BOOT ERROR] Illegal mapping signature: ");
874        boot_tty_putw(header->signature);
875        boot_tty_puts("\n");
876        boot_exit();
877    }
878
879#if BOOT_DEBUG_VIEW
880boot_print_mapping_info();
881#endif
882
883    // checking double definition of NB_CLUSTERS
884    if ( header->clusters != NB_CLUSTERS )
885    {
886        boot_tty_puts("\n[BOOT ERROR] Incoherent NB_CLUSTERS");
887        boot_tty_puts("\n             - In giet_config,  value = ");
888        boot_tty_putw ( NB_CLUSTERS );
889        boot_tty_puts("\n             - In mapping_info, value = ");
890        boot_tty_putw ( header->clusters );
891        boot_tty_puts("\n");
892        boot_exit();
893    }
894
895    // checking double definition of NB_TTYS
896    if ( header->ttys != NB_TTYS )
897    {
898        boot_tty_puts("\n[BOOT ERROR] Incoherent NB_TTYS");
899        boot_tty_puts("\n             - In giet_config,  value = ");
900        boot_tty_putw ( NB_TTYS );
901        boot_tty_puts("\n             - In mapping_info, value = ");
902        boot_tty_putw ( header->ttys );
903        boot_tty_puts("\n");
904        boot_exit();
905    }
906
907    // GIET_NB_PT2_MAX must be even
908    if ( (GIET_NB_PT2_MAX & 0x1) != 0 )
909    {
910        boot_tty_puts("\n[BOOT ERROR] : GIET_NB_PT2_MAX must be an even numver\n");
911        boot_tty_puts("\n");
912        boot_exit();
913    }
914
915    // number of virtual spaces no larger than GIET_NB_VSPACE_MAX
916    if ( header->vspaces > GIET_NB_VSPACE_MAX )
917    {
918        boot_tty_puts("\n[BOOT ERROR] : number of vspaces > GIET_NB_VSPACE_MAX\n");
919        boot_tty_puts("\n");
920        boot_exit();
921    }
922} // end boot_check_mapping()
923
924/////////////////////////////////////////////////////////////////////
925// This function builds the page tables for all virtual spaces
926// defined in the mapping_info data structure.
927// For each virtual space, it maps both the global virtual segments
928// (replicated in all vspaces), and the private virtuals segments.
929/////////////////////////////////////////////////////////////////////
930in_boot void boot_pt_init()
931{
932    mapping_header_t*   header = (mapping_header_t*)&seg_boot_mapping_base; 
933
934    mapping_vspace_t*   vspace = boot_get_vspace_base( header );     
935    mapping_pseg_t*     pseg   = boot_get_pseg_base( header ); 
936    mapping_vseg_t*     vseg   = boot_get_vseg_base( header );
937
938    unsigned int        vspace_id; 
939    unsigned int        vseg_id;
940    unsigned int        pseg_id;
941
942    // first loop on virtual spaces to map global vsegs
943    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
944    {
945
946#if BOOT_DEBUG_PT
947boot_tty_puts("\n******* mapping global vsegs in vspace ");
948boot_tty_puts(vspace[vspace_id].name);
949boot_tty_puts(" ********\n");
950#endif
951           
952        // physical page allocators must be re-initialised for each vspace
953        for ( pseg_id = 0 ; pseg_id < header->psegs ; pseg_id++ )
954        {
955            pseg[pseg_id].next_free_page = 0;
956        }
957
958        for ( vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
959        {
960            boot_vseg_map( &vseg[vseg_id] );
961        }
962    } 
963
964    // second loop on virtual spaces to map private vsegs
965    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
966    {
967
968#if BOOT_DEBUG_PT
969boot_tty_puts("\n******* mapping private vsegs in vspace ");
970boot_tty_puts(vspace[vspace_id].name);
971boot_tty_puts(" ********\n");
972#endif
973           
974        for ( vseg_id = vspace[vspace_id].vseg_offset ; 
975              vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
976              vseg_id++ )
977        {
978            boot_vseg_map( &vseg[vseg_id] ); 
979        }
980    } 
981
982    // third loop on the vspaces to build the page tables
983    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
984    {
985
986#if BOOT_DEBUG_PT
987boot_tty_puts("\n******* building page table for vspace ");
988boot_tty_puts(vspace[vspace_id].name);
989boot_tty_puts(" ********\n");
990#endif
991           
992        boot_vspace_pt_build( vspace_id );
993    } 
994} // end boot_pt_init()
995
996///////////////////////////////////////////////////////////////////////////////
997// This function sets the schedulers default values for all processors
998// (tasks <= 0, and current <= 0).
999// Then it scan all tasks (in all vspaces) to initialise the schedulers,
1000// the tasks contexts, as defined in the mapping_info data structure.
1001// A global TTY index is allocated to each task, as specified in the mapping.
1002// TTY0 is reserved for the kernel.
1003///////////////////////////////////////////////////////////////////////////////
1004in_boot void boot_tcg_init()
1005{
1006    mapping_header_t*   header = (mapping_header_t*)&seg_boot_mapping_base; 
1007
1008    mapping_vspace_t*   vspace  = boot_get_vspace_base( header );     
1009    mapping_vseg_t*     vseg    = boot_get_vseg_base( header );     
1010    mapping_cluster_t*  cluster = boot_get_cluster_base( header );
1011
1012    unsigned int*       start_vector_base;
1013
1014    unsigned int        base_tty_id = 1;     // TTY allocator
1015
1016    unsigned int        cluster_id; 
1017    unsigned int        proc_id; 
1018    unsigned int        vspace_id; 
1019    unsigned int        task_id;
1020
1021    // initialise the schedulers (not done by the compiler/loader)
1022    for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
1023    {
1024        for ( proc_id = 0 ; proc_id < cluster[cluster_id].procs ; proc_id++ )
1025        {
1026            if ( proc_id >= NB_PROCS )
1027            {
1028                boot_tty_puts("\n[BOOT ERROR] The number of processors in cluster ");
1029                boot_tty_putw( cluster_id );
1030                boot_tty_puts(" is larger than NB_PROCS \n");
1031                boot_exit();
1032            }
1033            _scheduler[cluster_id*NB_PROCS+proc_id].tasks   = 0;
1034            _scheduler[cluster_id*NB_PROCS+proc_id].current = 0;
1035        }
1036    }
1037
1038    // main loop on the virtual spaces
1039    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
1040    {
1041
1042#if BOOT_DEBUG_CTX
1043boot_tty_puts("\n******* mapping tasks and channels in vspace ");
1044boot_tty_puts(vspace[vspace_id].name);
1045boot_tty_puts(" ********\n");
1046#endif
1047
1048        // Get the physical address of the start_vector for the vspace.
1049        // The start_vector is stored at the beginning of the seg_data segment,
1050        // and contains the start addresses for all tasks defined in a vspace.
1051        // The seg_data segment must be the first vseg defined in
1052        // the mapping_info data structure.
1053        mapping_vseg_t* vseg_data = &vseg[ vspace[vspace_id].vseg_offset];
1054        start_vector_base = (unsigned int*)boot_translate( vseg_data->vbase,
1055                                                           vspace_id );
1056        // map tasks
1057        for ( task_id = vspace[vspace_id].task_offset ; 
1058              task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks) ; 
1059              task_id++ )
1060        {
1061            boot_task_map( task_id, 
1062                           vspace_id,
1063                           base_tty_id,
1064                           start_vector_base );           
1065        }
1066
1067        // increment TTY allocator
1068        base_tty_id = base_tty_id + vspace[vspace_id].ttys;   
1069    }
1070} // end boot_tc_init()
1071
1072/////////////////////////////////////////////////////////////////////
1073// This function signals the mapping completion by writing
1074// a new value in the mapping_info signature.
1075/////////////////////////////////////////////////////////////////////
1076in_boot void boot_mapping_done()
1077{
1078    mapping_header_t*   header = (mapping_header_t*)&seg_boot_mapping_base; 
1079    header->signature = OUT_MAPPING_SIGNATURE;
1080} // end boot_mapping_done()
1081
1082////////////////////////////////////////////////////////////////////////////////
1083//      boot_peri_init()
1084// This generic function initializes the interrupt vector, the ICU masks,
1085// and the timers for the context switch.
1086// The hardware parameters are NB_CLUSTERS, NB_PROCS, NB_TIMERS, NB_DMAS
1087// CLUSTER_SPAN, seg_icu_base, seg_timer_base.
1088// The number of processor per cluster cannot be larger than 8.
1089// The total number of TTYs cannot be larger than 15.
1090// The NB_TIMERS, NB_DMAS & NB_PROCS parameters must be equal.
1091////////////////////////////////////////////////////////////////////////////////
1092in_boot void boot_peri_init()
1093{
1094    mapping_header_t*   header = (mapping_header_t*)&seg_boot_mapping_base; 
1095    mapping_cluster_t* cluster = boot_get_cluster_base( header );
1096
1097    unsigned int cluster_id;
1098
1099    if ( NB_TIMERS != NB_PROCS )
1100    {
1101        boot_tty_puts("\n[BOOT ERROR] NB_TIMERS != NB_PROCS\n");
1102        boot_exit();
1103    }
1104    if ( NB_DMAS != NB_PROCS )
1105    {
1106        boot_tty_puts("\n[BOOT ERROR] NB_DMAS != NB_PROCS\n");
1107        boot_exit();
1108    }
1109
1110    // interrupt vector initialisation
1111
1112    _interrupt_vector[0]  = &_isr_ioc;
1113
1114    _interrupt_vector[1]  = &_isr_tty_get_0;
1115    _interrupt_vector[2]  = &_isr_tty_get_1;
1116    _interrupt_vector[3]  = &_isr_tty_get_2;
1117    _interrupt_vector[4]  = &_isr_tty_get_3;
1118    _interrupt_vector[5]  = &_isr_tty_get_4;
1119    _interrupt_vector[6]  = &_isr_tty_get_5;
1120    _interrupt_vector[7]  = &_isr_tty_get_6;
1121    _interrupt_vector[8]  = &_isr_tty_get_7;
1122    _interrupt_vector[9]  = &_isr_tty_get_8;
1123    _interrupt_vector[10] = &_isr_tty_get_9;
1124    _interrupt_vector[11] = &_isr_tty_get_10;
1125    _interrupt_vector[12] = &_isr_tty_get_11;
1126    _interrupt_vector[13] = &_isr_tty_get_12;
1127    _interrupt_vector[14] = &_isr_tty_get_13;
1128    _interrupt_vector[14] = &_isr_tty_get_14;
1129
1130
1131    _interrupt_vector[16] = &_isr_switch;
1132    _interrupt_vector[17] = &_isr_dma;
1133    _interrupt_vector[18] = &_isr_switch;
1134    _interrupt_vector[19] = &_isr_dma;
1135    _interrupt_vector[20] = &_isr_switch;
1136    _interrupt_vector[21] = &_isr_dma;
1137    _interrupt_vector[22] = &_isr_switch;
1138    _interrupt_vector[23] = &_isr_dma;
1139    _interrupt_vector[24] = &_isr_switch;
1140    _interrupt_vector[25] = &_isr_dma;
1141    _interrupt_vector[26] = &_isr_switch;
1142    _interrupt_vector[27] = &_isr_dma;
1143    _interrupt_vector[28] = &_isr_switch;
1144    _interrupt_vector[29] = &_isr_dma;
1145    _interrupt_vector[30] = &_isr_switch;
1146    _interrupt_vector[31] = &_isr_dma;
1147
1148    // ICU MASKs and TIMERS initialisation
1149
1150    volatile unsigned int* icu   = (unsigned int*)&seg_icu_base;
1151    volatile unsigned int* timer = (unsigned int*)&seg_timer_base;
1152   
1153    for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
1154    {
1155        if ( cluster[cluster_id].procs == 0 ) break;
1156
1157        icu[ICU_MASK_SET + 0*ICU_SPAN] = 0x000380FF;    // ICU_MASK for proc 0
1158        if ( _scheduler[cluster_id*NB_PROCS + 0].tasks > 1 )
1159        {
1160           timer[TIMER_PERIOD + 0*TIMER_SPAN] = GIET_TICK_VALUE;
1161           timer[TIMER_MODE   + 0*TIMER_SPAN] = 0x3;
1162        }
1163
1164        if ( cluster[cluster_id].procs == 1 ) break;
1165
1166        icu[ICU_MASK_SET + 1*ICU_SPAN] = 0x000C0000;    // ICU_MASK for proc 1
1167        if ( _scheduler[cluster_id*NB_PROCS + 1].tasks > 1 )
1168        {
1169           timer[TIMER_PERIOD + 1*TIMER_SPAN] = GIET_TICK_VALUE;
1170           timer[TIMER_MODE   + 1*TIMER_SPAN] = 0x3;
1171        }
1172
1173        if ( cluster[cluster_id].procs == 2 ) break;
1174
1175        icu[ICU_MASK_SET + 2*ICU_SPAN] = 0x00300000;    // ICU_MASK for proc 2
1176        if ( _scheduler[cluster_id*NB_PROCS + 2].tasks > 1 )
1177        {
1178           timer[TIMER_PERIOD + 2*TIMER_SPAN] = GIET_TICK_VALUE;
1179           timer[TIMER_MODE   + 2*TIMER_SPAN] = 0x3;
1180        }
1181
1182        if ( cluster[cluster_id].procs == 3 ) break;
1183
1184        icu[ICU_MASK_SET + 3*ICU_SPAN] = 0x00C00000;    // ICU_MASK for proc 3
1185        if ( _scheduler[cluster_id*NB_PROCS + 3].tasks > 1 )
1186        {
1187           timer[TIMER_PERIOD + 3*TIMER_SPAN] = GIET_TICK_VALUE;
1188           timer[TIMER_MODE   + 3*TIMER_SPAN] = 0x3;
1189        }
1190
1191        if ( cluster[cluster_id].procs == 4 ) break;
1192        icu[ICU_MASK_SET + 4*ICU_SPAN] = 0x03000000;    // ICU_MASK for proc 4
1193
1194        if ( _scheduler[cluster_id*NB_PROCS + 4].tasks > 1 )
1195        {
1196           timer[TIMER_PERIOD + 4*TIMER_SPAN] = GIET_TICK_VALUE;
1197           timer[TIMER_MODE   + 4*TIMER_SPAN] = 0x3;
1198        }
1199
1200        if ( cluster[cluster_id].procs == 5 ) break;
1201
1202        icu[ICU_MASK_SET + 5*ICU_SPAN] = 0x0C000000;    // ICU_MASK for proc 5
1203        if ( _scheduler[cluster_id*NB_PROCS + 5].tasks > 1 )
1204        {
1205           timer[TIMER_PERIOD + 5*TIMER_SPAN] = GIET_TICK_VALUE;
1206           timer[TIMER_MODE   + 5*TIMER_SPAN] = 0x3;
1207        }
1208
1209        if ( cluster[cluster_id].procs == 6 ) break;
1210
1211        icu[ICU_MASK_SET + 6*ICU_SPAN] = 0x30000000;    // ICU_MASK for proc 6
1212        if ( _scheduler[cluster_id*NB_PROCS + 6].tasks > 1 )
1213        {
1214           timer[TIMER_PERIOD + 6*TIMER_SPAN] = GIET_TICK_VALUE;
1215           timer[TIMER_MODE   + 6*TIMER_SPAN] = 0x3;
1216        }
1217
1218        if ( cluster[cluster_id].procs == 7 ) break;
1219
1220        icu[ICU_MASK_SET + 7*ICU_SPAN] = 0xC0000000;    // ICU_MASK for proc 7
1221        if ( _scheduler[cluster_id*NB_PROCS + 7].tasks > 1 )
1222        {
1223           timer[TIMER_PERIOD + 7*TIMER_SPAN] = GIET_TICK_VALUE;
1224           timer[TIMER_MODE   + 7*TIMER_SPAN] = 0x3;
1225        }
1226
1227        if ( cluster[cluster_id].procs > 8 ) 
1228        {
1229            boot_tty_puts("\n[BOOT ERROR] The number of processors per cluster\n");
1230            boot_tty_puts("               cannot be larger than 8\n");
1231            boot_exit();
1232        }
1233        icu   = icu   + (CLUSTER_SPAN>>2);
1234        timer = timer + (CLUSTER_SPAN>>2);
1235    }
1236} // end boot_peri_init()
1237 
1238////////////////////////////////////////////////////////////////////////////////////
1239// boot_init()
1240// This function is executed by one single processor to initialize the page
1241// tables, the tasks contexts and the peripherals, for all applications.
1242////////////////////////////////////////////////////////////////////////////////////
1243in_boot void boot_init()
1244{
1245    // checking mapping_info
1246    boot_check_mapping();
1247
1248    // building page tables
1249    boot_pt_init();
1250    boot_tty_puts("\n[BOOT] Page Tables completed at cycle ");
1251    boot_tty_putw( boot_time() );
1252    boot_tty_puts("\n");
1253
1254    // building tasks contexts
1255    boot_tcg_init();
1256    boot_tty_puts("\n[BOOT] Task Contexts completed at cycle ");
1257    boot_tty_putw( boot_time() );
1258    boot_tty_puts("\n");
1259
1260    // Initialize peripherals
1261    boot_peri_init();
1262    boot_tty_puts("\n[BOOT] Peripherals completed at cycle ");
1263    boot_tty_putw( boot_time() );
1264    boot_tty_puts("\n");
1265
1266    // signals completion to all processors
1267    boot_mapping_done();
1268
1269} // end boot_init()
1270
1271// Local Variables:
1272// tab-width: 4
1273// c-basic-offset: 4
1274// c-file-offsets:((innamespace . 0)(inline-open . 0))
1275// indent-tabs-mode: nil
1276// End:
1277
1278// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
1279
Note: See TracBrowser for help on using the repository browser.