source: soft/giet_vm/boot/boot_init.c @ 208

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

Several bugs have been fixed to support TSAR multi-cluster architecture
such as the "tsarv4-generic_mmu" platform.

File size: 67.0 KB
Line 
1//////////////////////////////////////////////////////////////////////////////////
2// File     : boot_init.c
3// Date     : 01/04/2012
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// The boot_init.c file is part of the GIET-VM nano-kernel.
8// This code is executed in the boot phase by proc[0] to initialize the
9//  peripherals and the kernel data structures:
10// - pages tables for the various vspaces
11// - shedulers for processors (including the tasks contexts and interrupt vectors)
12//
13// The GIET-VM uses the paged virtual memory and the MAPPING_INFO binary file
14// to provides two services:
15// 1) classical memory protection, when several independant applications compiled
16//    in different virtual spaces are executing on the same hardware platform.
17// 2) data placement in NUMA architectures, when we want to control the placement
18//    of the software objects (virtual segments) on the physical memory banks.
19//
20// The MAPPING_INFO binary data structure must be loaded in the the seg_boot_mapping
21// segment (at address seg_mapping_base).
22// This MAPPING_INFO data structure defines both the hardware architecture
23// and the mapping:
24// - physical segmentation of the physical address space,
25// - virtual spaces definition (one multi-task application per vspace),
26// - placement of virtual objects (vobj) in the virtual segments (vseg).
27// - placement of virtual segments (vseg) in the physical segments (pseg).
28// - placement of tasks on the processors,
29//
30// The page table are statically build in the boot phase, and they do not
31// change during execution. The GIET uses only 4 Kbytes pages.
32// As most applications use only a limited number of segments, the number of PT2s
33// actually used by a given virtual space is generally smaller than 2048, and is
34// computed during the boot phase.
35// The max number of virtual spaces (GIET_NB_VSPACE_MAX) is a configuration parameter.
36//
37// Each page table (one page table per virtual space) is monolithic, and
38// contains one PT1 and (GIET_NB_PT2_MAX) PT2s. The PT1 is addressed using the ix1 field
39// (11 bits) of the VPN, and the selected PT2 is addressed using the ix2 field (9 bits).
40// - PT1[2048] : a first 8K aligned array of unsigned int, indexed by the (ix1) field of VPN.
41//   Each entry in the PT1 contains a 32 bits PTD. The MSB bit PTD[31] is
42//   the PTD valid bit, and LSB bits PTD[19:0] are the 20 MSB bits of the physical base
43//   address of the selected PT2.
44//   The PT1 contains 2048 PTD of 4 bytes => 8K bytes.
45// - PT2[1024][GIET_NB_PT2_MAX] : an array of array of unsigned int.
46//   Each PT2[1024] must be 4K aligned,  and each entry in a PT2 contains two unsigned int:
47//   the first word contains the protection flags, and the second word contains the PPN.
48//   Each PT2 contains 512 PTE2 of 8bytes => 4K bytes.
49// The total size of a page table is finally = 8K + (GIET_NB_PT2_MAX)*4K bytes.
50////////////////////////////////////////////////////////////////////////////////////
51
52#include <common.h>
53#include <mips32_registers.h>
54#include <giet_config.h>
55#include <mapping_info.h>
56#include <mwmr_channel.h>
57#include <barrier.h>
58#include <irq_handler.h>
59#include <ctx_handler.h>
60#include <vm_handler.h>
61#include <hwr_mapping.h>
62
63#include <stdarg.h>
64
65#if !defined(NB_CLUSTERS)
66# error The NB_CLUSTERS value must be defined in the 'giet_config.h' file !
67#endif
68
69#if !defined(NB_PROCS_MAX)
70# error The NB_PROCS_MAX value must be defined in the 'giet_config.h' file !
71#endif
72
73#if !defined(GIET_NB_VSPACE_MAX)
74# error The GIET_NB_VSPACE_MAX value must be defined in the 'giet_config.h' file !
75#endif
76
77////////////////////////////////////////////////////////////////////////////
78//      Global variables for boot code
79// As both the page tables and the schedulers are physically distributed,
80// these global variables are just arrays of pointers.
81////////////////////////////////////////////////////////////////////////////
82
83// Page table pointers array
84page_table_t*           boot_ptabs_vaddr[GIET_NB_VSPACE_MAX];
85page_table_t*           boot_ptabs_paddr[GIET_NB_VSPACE_MAX];
86
87// Scheduler pointers array
88static_scheduler_t*     boot_schedulers_paddr[NB_CLUSTERS * NB_PROCS_MAX];
89
90// Next free PT2 index array
91unsigned int            boot_next_free_pt2[GIET_NB_VSPACE_MAX] =
92                             { [0 ... GIET_NB_VSPACE_MAX-1] = 0 };
93
94// Max PT2 index
95unsigned int            boot_max_pt2[GIET_NB_VSPACE_MAX] =
96                            { [0 ... GIET_NB_VSPACE_MAX-1] = 0 };
97
98
99//////////////////////////////////////////////////////////////////////////////
100// boot_procid()
101//////////////////////////////////////////////////////////////////////////////
102inline unsigned int boot_procid()
103{
104    unsigned int ret;
105    asm volatile("mfc0 %0, $15, 1" : "=r"(ret));
106    return (ret & 0x3FF);
107}
108//////////////////////////////////////////////////////////////////////////////
109// boot_proctime()
110//////////////////////////////////////////////////////////////////////////////
111inline unsigned int boot_proctime()
112{
113    unsigned int ret;
114    asm volatile("mfc0 %0, $9" : "=r"(ret));
115    return ret;
116}
117//////////////////////////////////////////////////////////////////////////////
118// boot_exit()
119//////////////////////////////////////////////////////////////////////////////
120void boot_exit()
121{
122    while(1) asm volatile("nop");
123}
124//////////////////////////////////////////////////////////////////////////////
125// boot_eret()
126// The address of this function is used to initialise the return address (RA)
127// in all task contexts (when the task has never been executed.
128/////////////////////////////////"/////////////////////////////////////////////
129void boot_eret()
130{
131    asm volatile("eret");
132}
133//////////////////////////////////////////////////////////////////////////////
134// boot_scheduler_set_context()
135// This function set a context slot in a scheduler, after a temporary
136// desactivation of the DTLB (because we use the scheduler physical address).
137// - gpid   : global processor/scheduler index
138// - ltid   : local task index
139// - slotid : context slot index
140// - value  : value to be written
141//////////////////////////////////////////////////////////////////////////////
142inline void boot_scheduler_set_context( unsigned int gpid, 
143                                        unsigned int ltid, 
144                                        unsigned int slotid,
145                                        unsigned int value )
146{
147    // get scheduler physical address
148    static_scheduler_t*     psched = boot_schedulers_paddr[gpid];
149   
150    // get slot physical address
151    unsigned int*           pslot  = &(psched->context[ltid][slotid]);
152
153    asm volatile ( "li      $26,    0xB     \n"
154                   "mtc2    $26,    $1      \n"     /* desactivate DTLB */
155                   "sw      %1,     0(%0)   \n"     /* *pslot <= value  */
156                   "li      $26,    0xF     \n" 
157                   "mtc2    $26,    $1      \n"     /* activate DTLB    */
158                   : 
159                   : "r"(pslot), "r"(value) 
160                   : "$26" );
161}
162//////////////////////////////////////////////////////////////////////////////
163// boot_scheduler_set_itvector()
164// This function set an interrupt vector slot in a scheduler, after a temporary
165// desactivation of the DTLB (because we use the scheduler physical address).
166// - gpid   : global processor/scheduler index
167// - slotid : context slot index
168// - value  : value to be written
169//////////////////////////////////////////////////////////////////////////////
170inline void boot_scheduler_set_itvector( unsigned int gpid, 
171                                         unsigned int slotid,
172                                         unsigned int value )
173{
174    // get scheduler physical address
175    static_scheduler_t*     psched = boot_schedulers_paddr[gpid];
176   
177    // get slot physical address
178    unsigned int*           pslot  = &(psched->interrupt_vector[slotid]);
179
180    asm volatile ( "li      $26,    0xB     \n"
181                   "mtc2    $26,    $1      \n"     /* desactivate DTLB */
182                   "sw      %1,     0(%0)   \n"     /* *pslot <= value  */
183                   "li      $26,    0xF     \n" 
184                   "mtc2    $26,    $1      \n"     /* activate DTLB    */
185                   : 
186                   : "r"(pslot), "r"(value) 
187                   : "$26" );
188}
189//////////////////////////////////////////////////////////////////////////////
190// boot_scheduler_get_tasks()
191// This function returns the "tasks" field of a scheduler, after temporary
192// desactivation of the DTLB (because we use the scheduler physical address).
193// - gpid   : global processor/scheduler index
194//////////////////////////////////////////////////////////////////////////////
195inline unsigned int boot_scheduler_get_tasks( unsigned int gpid )
196{
197    unsigned int    ret; 
198
199    // get scheduler physical address
200    static_scheduler_t*     psched = boot_schedulers_paddr[gpid];
201   
202    // get tasks physical address
203    unsigned int*           ptasks = &(psched->tasks);
204
205    asm volatile ( "li      $26,    0xB     \n"
206                   "mtc2    $26,    $1      \n"     /* desactivate DTLB */
207                   "lw      %0,     0(%1)   \n"     /* ret <= *ptasks   */
208                   "li      $26,    0xF     \n" 
209                   "mtc2    $26,    $1      \n"     /* activate DTLB    */
210                   : "=r"(ret)
211                   : "r"(ptasks) 
212                   : "$26" );
213    return ret;
214}
215//////////////////////////////////////////////////////////////////////////////
216// boot_scheduler_set_tasks()
217// This function set the "tasks" field of a scheduler, after temporary
218// desactivation of the DTLB (because we use the scheduler physical address).
219// - gpid   : global processor/scheduler index
220// - value  : value to be written
221//////////////////////////////////////////////////////////////////////////////
222inline void boot_scheduler_set_tasks( unsigned int gpid,
223                                      unsigned int value )
224{
225    // get scheduler physical address
226    static_scheduler_t*     psched = boot_schedulers_paddr[gpid];
227   
228    // get tasks physical address
229    unsigned int*           ptasks = &(psched->tasks);
230
231    asm volatile ( "li      $26,    0xB     \n"
232                   "mtc2    $26,    $1      \n"     /* desactivate DTLB */
233                   "sw      %1,     0(%0)   \n"     /* *ptasks <= value */
234                   "li      $26,    0xF     \n" 
235                   "mtc2    $26,    $1      \n"     /* activate DTLB    */
236                   : 
237                   : "r"(ptasks), "r"(value) 
238                   : "$26" );
239}
240//////////////////////////////////////////////////////////////////////////////
241// boot_scheduler_set_current()
242// This function set the "current" field of a scheduler, after temporary
243// desactivation of the DTLB (because we use the scheduler physical address).
244// - gpid   : global processor/scheduler index
245// - value  : value to be written
246//////////////////////////////////////////////////////////////////////////////
247inline void boot_scheduler_set_current( unsigned int gpid,
248                                 unsigned int value )
249{
250    // get scheduler physical address
251    static_scheduler_t*     psched = boot_schedulers_paddr[gpid];
252   
253    // get tasks physical address
254    unsigned int*           pcur   = &(psched->current);
255
256    asm volatile ( "li      $26,    0xB     \n"
257                   "mtc2    $26,    $1      \n"     /* desactivate DTLB */
258                   "sw      %1,     0(%0)   \n"     /* *pcur   <= value */
259                   "li      $26,    0xF     \n" 
260                   "mtc2    $26,    $1      \n"     /* activate DTLB    */
261                   : 
262                   : "r"(pcur), "r"(value) 
263                   : "$26" );
264}
265//////////////////////////////////////////////////////////////////////////////
266// boot_set_mmu_ptpr()
267// This function set a new value for the MMU PTPR register.
268//////////////////////////////////////////////////////////////////////////////
269inline void boot_set_mmu_ptpr( unsigned int val )
270{
271    asm volatile("mtc2  %0, $0" : : "r"(val) );
272}
273
274//////////////////////////////////////////////////////////////////////////////
275// boot_set_mmu_mode()
276// This function set a new value for the MMU MODE register.
277//////////////////////////////////////////////////////////////////////////////
278inline void boot_set_mmu_mode( unsigned int val )
279{
280    asm volatile("mtc2  %0, $1" : : "r"(val) );
281}
282////////////////////////////////////////////////////////////////////////////
283// boot_puts()
284// (it uses TTY0)
285////////////////////////////////////////////////////////////////////////////
286void boot_puts(const char *buffer) 
287{
288    unsigned int* tty_address = (unsigned int*)( (char*)&seg_tty_base +
289                                (CLUSTER_IO_ID * (unsigned)CLUSTER_SIZE) );
290    unsigned int n;
291
292    for ( n=0; n<100; n++)
293    {
294        if (buffer[n] == 0) break;
295        tty_address[TTY_WRITE] = (unsigned int)buffer[n];
296    }
297} 
298////////////////////////////////////////////////////////////////////////////
299// boot_putx()
300// (it uses TTY0)
301////////////////////////////////////////////////////////////////////////////
302void boot_putx(unsigned int val)
303{
304    static const char   HexaTab[] = "0123456789ABCDEF";
305    char                buf[11];
306    unsigned int        c;
307
308    buf[0]  = '0';
309    buf[1]  = 'x';
310    buf[10] = 0;
311
312    for ( c = 0 ; c < 8 ; c++ )
313    { 
314        buf[9-c] = HexaTab[val&0xF];
315        val = val >> 4;
316    }
317    boot_puts(buf);
318}
319////////////////////////////////////////////////////////////////////////////
320// boot_putd()
321// (it uses TTY0)
322////////////////////////////////////////////////////////////////////////////
323void boot_putd(unsigned int val)
324{
325    static const char   DecTab[] = "0123456789";
326    char                buf[11];
327    unsigned int        i;
328    unsigned int        first;
329
330    buf[10] = 0;
331
332    for ( i = 0 ; i < 10 ; i++ )
333    {
334        if ((val != 0) || (i == 0))
335        {
336            buf[9-i] = DecTab[val % 10];
337            first    = 9-i;
338        }
339        else
340        {
341            break;
342        }
343        val /= 10;
344    }
345    boot_puts( &buf[first] );
346}
347
348/////////////////////////////////////////////////////////////////////////////
349//  mapping_info data structure access functions
350/////////////////////////////////////////////////////////////////////////////
351inline mapping_cluster_t* boot_get_cluster_base( mapping_header_t* header )
352{
353    return   (mapping_cluster_t*) ((char*)header +
354                                  MAPPING_HEADER_SIZE);
355}
356/////////////////////////////////////////////////////////////////////////////
357inline mapping_pseg_t* boot_get_pseg_base( mapping_header_t* header )
358{
359    return   (mapping_pseg_t*)    ((char*)header +
360                                  MAPPING_HEADER_SIZE +
361                                  MAPPING_CLUSTER_SIZE*header->clusters);
362}
363/////////////////////////////////////////////////////////////////////////////
364inline mapping_vspace_t* boot_get_vspace_base( mapping_header_t* header )
365{
366    return   (mapping_vspace_t*)  ((char*)header +
367                                  MAPPING_HEADER_SIZE +
368                                  MAPPING_CLUSTER_SIZE*header->clusters +
369                                  MAPPING_PSEG_SIZE*header->psegs);
370}
371/////////////////////////////////////////////////////////////////////////////
372inline mapping_vseg_t* boot_get_vseg_base( mapping_header_t* header )
373{
374    return   (mapping_vseg_t*)    ((char*)header +
375                                  MAPPING_HEADER_SIZE +
376                                  MAPPING_CLUSTER_SIZE*header->clusters +
377                                  MAPPING_PSEG_SIZE*header->psegs +
378                                  MAPPING_VSPACE_SIZE*header->vspaces);
379}
380/////////////////////////////////////////////////////////////////////////////
381inline mapping_vobj_t* boot_get_vobj_base( mapping_header_t* header )
382{
383    return   (mapping_vobj_t*)   ((char*)header +
384                                  MAPPING_HEADER_SIZE +
385                                  MAPPING_CLUSTER_SIZE*header->clusters +
386                                  MAPPING_PSEG_SIZE*header->psegs +
387                                  MAPPING_VSPACE_SIZE*header->vspaces +
388                                  MAPPING_VSEG_SIZE*header->vsegs );
389}
390/////////////////////////////////////////////////////////////////////////////
391inline mapping_task_t* boot_get_task_base( mapping_header_t* header )
392{
393    return   (mapping_task_t*)    ((char*)header +
394                                  MAPPING_HEADER_SIZE +
395                                  MAPPING_CLUSTER_SIZE*header->clusters +
396                                  MAPPING_PSEG_SIZE*header->psegs +
397                                  MAPPING_VSPACE_SIZE*header->vspaces +
398                                  MAPPING_VSEG_SIZE*header->vsegs +
399                                  MAPPING_VOBJ_SIZE*header->vobjs );
400}
401/////////////////////////////////////////////////////////////////////////////
402inline mapping_proc_t* boot_get_proc_base( mapping_header_t* header )
403{
404    return   (mapping_proc_t*)    ((char*)header +
405                                  MAPPING_HEADER_SIZE +
406                                  MAPPING_CLUSTER_SIZE*header->clusters +
407                                  MAPPING_PSEG_SIZE*header->psegs +
408                                  MAPPING_VSPACE_SIZE*header->vspaces +
409                                  MAPPING_VSEG_SIZE*header->vsegs +
410                                  MAPPING_VOBJ_SIZE*header->vobjs +
411                                  MAPPING_TASK_SIZE*header->tasks );
412}
413/////////////////////////////////////////////////////////////////////////////
414inline mapping_irq_t* boot_get_irq_base( mapping_header_t* header )
415{
416    return   (mapping_irq_t*)     ((char*)header +
417                                  MAPPING_HEADER_SIZE +
418                                  MAPPING_CLUSTER_SIZE*header->clusters +
419                                  MAPPING_PSEG_SIZE*header->psegs +
420                                  MAPPING_VSPACE_SIZE*header->vspaces +
421                                  MAPPING_VSEG_SIZE*header->vsegs +
422                                  MAPPING_VOBJ_SIZE*header->vobjs +
423                                  MAPPING_TASK_SIZE*header->tasks +
424                                  MAPPING_PROC_SIZE*header->procs );
425}
426/////////////////////////////////////////////////////////////////////////////
427inline mapping_coproc_t* boot_get_coproc_base( mapping_header_t* header )
428{
429    return  (mapping_coproc_t*)   ((char*)header +
430                                  MAPPING_HEADER_SIZE +
431                                  MAPPING_CLUSTER_SIZE*header->clusters +
432                                  MAPPING_PSEG_SIZE*header->psegs +
433                                  MAPPING_VSPACE_SIZE*header->vspaces +
434                                  MAPPING_VOBJ_SIZE*header->vobjs +
435                                  MAPPING_VSEG_SIZE*header->vsegs +
436                                  MAPPING_TASK_SIZE*header->tasks +
437                                  MAPPING_PROC_SIZE*header->procs +
438                                  MAPPING_IRQ_SIZE*header->irqs );
439}
440///////////////////////////////////////////////////////////////////////////////////
441inline mapping_cp_port_t* boot_get_cp_port_base( mapping_header_t* header )
442{
443    return (mapping_cp_port_t*)   ((char*)header +
444                                  MAPPING_HEADER_SIZE +
445                                  MAPPING_CLUSTER_SIZE*header->clusters +
446                                  MAPPING_PSEG_SIZE*header->psegs +
447                                  MAPPING_VSPACE_SIZE*header->vspaces +
448                                  MAPPING_VOBJ_SIZE*header->vobjs +
449                                  MAPPING_VSEG_SIZE*header->vsegs +
450                                  MAPPING_TASK_SIZE*header->tasks +
451                                  MAPPING_PROC_SIZE*header->procs +
452                                  MAPPING_IRQ_SIZE*header->irqs +
453                                  MAPPING_COPROC_SIZE*header->coprocs );
454}
455///////////////////////////////////////////////////////////////////////////////////
456inline mapping_periph_t* boot_get_periph_base( mapping_header_t* header )
457{
458    return (mapping_periph_t*)    ((char*)header +
459                                  MAPPING_HEADER_SIZE +
460                                  MAPPING_CLUSTER_SIZE*header->clusters +
461                                  MAPPING_PSEG_SIZE*header->psegs +
462                                  MAPPING_VSPACE_SIZE*header->vspaces +
463                                  MAPPING_VOBJ_SIZE*header->vobjs +
464                                  MAPPING_VSEG_SIZE*header->vsegs +
465                                  MAPPING_TASK_SIZE*header->tasks +
466                                  MAPPING_PROC_SIZE*header->procs +
467                                  MAPPING_IRQ_SIZE*header->irqs +
468                                  MAPPING_COPROC_SIZE*header->coprocs +
469                                  MAPPING_CP_PORT_SIZE*header->cp_ports );
470}
471
472//////////////////////////////////////////////////////////////////////////////
473//     boot_pseg_get()
474// This function returns the pointer on a physical segment
475// identified  by the pseg index.
476//////////////////////////////////////////////////////////////////////////////
477mapping_pseg_t* boot_pseg_get( unsigned int seg_id)
478{
479    mapping_header_t* header = (mapping_header_t*)&seg_mapping_base;
480    mapping_pseg_t*   pseg   = boot_get_pseg_base( header );
481
482    // checking argument
483    if ( seg_id >= header->psegs )
484    {
485        boot_puts("\n[BOOT ERROR] : seg_id argument too large\n");
486        boot_puts("               in function boot_pseg_get()\n");
487        boot_exit();
488    }
489
490    return &pseg[seg_id];                                   
491} // end boot_pseg_get()
492
493//////////////////////////////////////////////////////////////////////////////
494// boot_add_pte()
495// This function registers a new PTE in the page table pointed
496// by the vspace_id argument, and updates both PT1 and PT2.
497// A new PT2 is used when required.
498// As the set of PT2s is implemented as a fixed size array (no dynamic
499// allocation), this function checks a possible overflow of the PT2 array.
500//
501// The global parameter is a boolean indicating wether a global vseg is
502// being mapped.
503//////////////////////////////////////////////////////////////////////////////
504void boot_add_pte( unsigned int    vspace_id,   
505                   unsigned int    vpn,           
506                   unsigned int    flags,
507                   unsigned int    ppn )
508{
509    unsigned int    ix1;
510    unsigned int    ix2;
511    unsigned int    ptba;       // PT2 base address
512    unsigned int    pt2_id;     // PT2 index
513    unsigned int*   pt_flags;   // pointer on the pte_flags = &PT2[2*ix2]   
514    unsigned int*   pt_ppn;     // pointer on the pte_ppn   = &PT2[2*ix2+1] 
515
516    ix1 = vpn >> 9;             // 11 bits
517    ix2 = vpn  & 0x1FF;         //  9 bits
518
519    // check that the boot_max_pt2[vspace_id] has been set
520    unsigned int max_pt2   = boot_max_pt2[vspace_id];
521
522    if(max_pt2 == 0)
523    {
524        boot_puts("Unfound page table for vspace ");
525        boot_putd(vspace_id);
526        boot_puts("\n");
527        boot_exit();
528    }
529
530    // get page table physical address
531    page_table_t* pt = boot_ptabs_paddr[vspace_id];
532
533    if ( (pt->pt1[ix1] & PTE_V) == 0 )   // set a new PTD in PT1
534    {
535        pt2_id = boot_next_free_pt2[vspace_id];
536        if ( pt2_id == max_pt2 )
537        {
538            boot_puts("\n[BOOT ERROR] in boot_add_pte() function\n");
539            boot_puts("the length of the ptab vobj is too small\n"); 
540            boot_exit();
541        }
542        else
543        {
544            ptba = (unsigned int)pt + PT1_SIZE + PT2_SIZE*pt2_id;
545            pt->pt1[ix1] = PTE_V | PTE_T | (ptba >> 12);   
546            boot_next_free_pt2[vspace_id] = pt2_id + 1;
547        }
548    }
549    else
550    {
551        ptba = pt->pt1[ix1] << 12;
552    }
553
554    // set PTE2 after checking double mapping error
555    pt_flags = (unsigned int*)(ptba + 8*ix2);
556    pt_ppn   = (unsigned int*)(ptba + 8*ix2 + 4);
557
558    if ( ( *pt_flags & PTE_V) != 0 )    // page already mapped
559    {
560        boot_puts("\n[BOOT ERROR] double mapping in vspace ");
561        boot_putd( vspace_id );
562        boot_puts(" for vpn = ");
563        boot_putx( vpn );
564        boot_puts("\n");
565        boot_exit();
566    }
567
568    // set PTE2
569    *pt_flags = flags;
570    *pt_ppn   = ppn;
571
572} // end boot_add_pte()
573               
574/////////////////////////////////////////////////////////////////////
575// This function build the page table for a given vspace.
576// The physical base addresses for all vsegs (global and private)
577// must have been previously computed.
578// It initializes the MWMR channels.
579/////////////////////////////////////////////////////////////////////
580void boot_vspace_pt_build( unsigned int vspace_id )
581{
582    unsigned int    vseg_id;
583    unsigned int    npages;
584    unsigned int    ppn;
585    unsigned int    vpn;
586    unsigned int    flags;
587    unsigned int    page_id;
588
589    mapping_header_t*  header = (mapping_header_t*)&seg_mapping_base; 
590    mapping_vspace_t*  vspace = boot_get_vspace_base( header );
591    mapping_vseg_t*    vseg   = boot_get_vseg_base( header );
592   
593    // private segments
594    for ( vseg_id = vspace[vspace_id].vseg_offset ; 
595          vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
596          vseg_id++ )
597    {
598        vpn       = vseg[vseg_id].vbase >> 12;
599        ppn       = vseg[vseg_id].pbase >> 12;
600        npages    = vseg[vseg_id].length >> 12;
601        if ( (vseg[vseg_id].length & 0xFFF) != 0 ) npages++;
602
603        flags = PTE_V;
604        if ( vseg[vseg_id].mode & C_MODE_MASK )  flags = flags | PTE_C;
605        if ( vseg[vseg_id].mode & X_MODE_MASK )  flags = flags | PTE_X;
606        if ( vseg[vseg_id].mode & W_MODE_MASK )  flags = flags | PTE_W;
607        if ( vseg[vseg_id].mode & U_MODE_MASK )  flags = flags | PTE_U;
608
609#if BOOT_DEBUG_PT
610boot_puts( vseg[vseg_id].name );
611boot_puts(" : flags = ");
612boot_putx( flags );
613boot_puts(" / npages = ");
614boot_putd( npages );
615boot_puts(" / pbase = ");
616boot_putx( vseg[vseg_id].pbase );
617boot_puts("\n");
618#endif       
619        // loop on 4K pages
620        for ( page_id = 0 ; page_id < npages ; page_id++ )
621        {
622            boot_add_pte( vspace_id,
623                          vpn,
624                          flags,
625                          ppn );
626            vpn++;
627            ppn++;
628        }
629    }
630
631    // global segments
632    for ( vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
633    {
634        vpn       = vseg[vseg_id].vbase >> 12;
635        ppn       = vseg[vseg_id].pbase >> 12;
636        npages    = vseg[vseg_id].length >> 12;
637        if ( (vseg[vseg_id].length & 0xFFF) != 0 ) npages++;
638
639        flags = PTE_V;
640        if ( vseg[vseg_id].mode & C_MODE_MASK )  flags = flags | PTE_C;
641        if ( vseg[vseg_id].mode & X_MODE_MASK )  flags = flags | PTE_X;
642        if ( vseg[vseg_id].mode & W_MODE_MASK )  flags = flags | PTE_W;
643        if ( vseg[vseg_id].mode & U_MODE_MASK )  flags = flags | PTE_U;
644
645#if BOOT_DEBUG_PT
646boot_puts( vseg[vseg_id].name );
647boot_puts(" / flags = ");
648boot_putx( flags );
649boot_puts(" / npages = ");
650boot_putd( npages );
651boot_puts(" / pbase = ");
652boot_putx( vseg[vseg_id].pbase );
653boot_puts("\n");
654#endif       
655        // loop on 4K pages
656        for ( page_id = 0 ; page_id < npages ; page_id++ )
657        {
658            boot_add_pte( vspace_id,
659                          vpn,
660                          flags,
661                          ppn );
662            vpn++;
663            ppn++;
664        }
665    }
666
667} // end boot_vspace_pt_build()
668
669///////////////////////////////////////////////////////////////////////////
670// Align the value "toAlign" to the required alignement indicated by
671// alignPow2 ( the logarithme of 2 the alignement).
672///////////////////////////////////////////////////////////////////////////
673unsigned int align_to( unsigned int toAlign, 
674                       unsigned int alignPow2)
675{
676    unsigned int    mask = (1 << alignPow2) - 1;
677    return ((toAlign + mask ) & ~mask ); 
678}
679
680///////////////////////////////////////////////////////////////////////////
681// This function compute the physical base address for a vseg
682// as specified in the mapping info data structure.
683// It updates the pbase and the length fields of the vseg.
684// It updates the pbase and vbase fields of all vobjs in the vseg.
685// It updates the next_base field of the pseg, and checks overflow.
686// It updates the boot_ptabs_paddr[] and boot_ptabs_vaddr[] arrays.
687// It is a global vseg if vspace_id = (-1).
688///////////////////////////////////////////////////////////////////////////
689void boot_vseg_map( mapping_vseg_t*     vseg, 
690                    unsigned int        vspace_id ) 
691{
692    unsigned int        vobj_id;
693    unsigned int        cur_vaddr;
694    unsigned int        cur_paddr;
695    mapping_header_t*   header = (mapping_header_t*)&seg_mapping_base; 
696    mapping_vobj_t*     vobj   = boot_get_vobj_base( header );
697 
698    // get physical segment pointer
699    mapping_pseg_t*  pseg = boot_pseg_get( vseg->psegid );
700
701    // compute vseg physical base address
702    if ( vseg->ident != 0 )            // identity mapping required
703    {
704         vseg->pbase = vseg->vbase;
705    }
706    else                                // unconstrained mapping
707    {
708        vseg->pbase = pseg->next_base;
709
710        // test alignment constraint
711        if ( vobj[vseg->vobj_offset].align )
712        {
713            vseg->pbase = align_to( vseg->pbase, vobj[vseg->vobj_offset].align );
714        }
715    }
716   
717    // loop on vobjs contained in vseg to :
718    // (1) computes the length of the vseg,
719    // (2) initialise the vaddr and paddr fields of all vobjs,
720    // (3) initialise the page table pointers arrays
721
722    cur_vaddr = vseg->vbase;
723    cur_paddr = vseg->pbase;
724
725    for( vobj_id = vseg->vobj_offset; 
726         vobj_id < (vseg->vobj_offset + vseg->vobjs); 
727         vobj_id++)
728    {
729        if ( vobj[vobj_id].align )
730        {
731            cur_paddr = align_to(cur_paddr, vobj[vobj_id].align);
732        }
733
734        // set vaddr/paddr for current vobj
735        vobj[vobj_id].vaddr = cur_vaddr;       
736        vobj[vobj_id].paddr = cur_paddr; 
737     
738        // initialise boot_ptabs_vaddr[] if current vobj is a PTAB
739        if ( vobj[vobj_id].type == VOBJ_TYPE_PTAB )
740        {
741            if(vspace_id == ((unsigned int) -1))    // global vseg
742            {
743                boot_puts( "\n[BOOT ERROR] in boot_vseg_map() function: " );
744                boot_puts( "a PTAB vobj cannot be global" );
745                boot_exit();
746            }
747
748            // we need at least one PT2 => ( boot_max_pt2[vspace_id] >= 1)
749            if(vobj[vobj_id].length < (PT1_SIZE + PT2_SIZE) ) 
750            {
751                boot_puts( "\n[BOOT ERROR] in boot_vseg_map() function, " );
752                boot_puts("PTAB too small, minumum size is: ");
753                boot_putx( PT1_SIZE + PT2_SIZE);
754                boot_exit();
755            }
756
757            // register both physical and virtual page table address
758            boot_ptabs_vaddr[vspace_id] = (page_table_t*)vobj[vobj_id].vaddr;
759            boot_ptabs_paddr[vspace_id] = (page_table_t*)vobj[vobj_id].paddr;
760
761            /* computing the number of second level page */
762            boot_max_pt2[vspace_id] = (vobj[vobj_id].length - PT1_SIZE) / PT2_SIZE;
763        }
764
765        // set next vaddr/paddr
766        cur_vaddr += vobj[vobj_id].length;
767        cur_paddr += vobj[vobj_id].length; 
768
769    } // end for vobjs
770   
771    //set the vseg length
772    vseg->length = align_to( (cur_paddr - vseg->pbase), 12);
773
774    // checking pseg overflow
775    if ( (vseg->pbase < pseg->base) || 
776         ((vseg->pbase + vseg->length) > (pseg->base + pseg->length)) )
777    {
778        boot_puts("\n[BOOT ERROR] in boot_vseg_map() function\n");
779        boot_puts("impossible mapping for virtual segment: ");
780        boot_puts( vseg->name ); 
781        boot_puts("\n"); 
782        boot_puts("vseg pbase = ");
783        boot_putx( vseg->pbase ); 
784        boot_puts("\n"); 
785        boot_puts("vseg length = ");
786        boot_putx( vseg->length ); 
787        boot_puts("\n"); 
788        boot_puts("pseg pbase = ");
789        boot_putx( pseg->base ); 
790        boot_puts("\n"); 
791        boot_puts("pseg length = ");
792        boot_putx( pseg->length ); 
793        boot_puts("\n"); 
794        boot_exit();
795    }
796
797    // set the next_base field in vseg
798    if ( vseg->ident == 0 )
799        pseg->next_base = vseg->pbase + vseg->length;
800
801#if BOOT_DEBUG_PT
802boot_puts( vseg->name );
803boot_puts(" : len = ");
804boot_putx( vseg->length );
805boot_puts(" / vbase = ");
806boot_putx( vseg->vbase );
807boot_puts(" / pbase = ");
808boot_putx( vseg->pbase );
809boot_puts("\n");
810#endif 
811
812} // end boot_vseg_map()
813
814/////////////////////////////////////////////////////////////////////
815// This function checks consistence beween the  mapping_info data
816// structure (soft), and the giet_config file (hard).
817/////////////////////////////////////////////////////////////////////
818void boot_check_mapping()
819{
820    mapping_header_t*   header  = (mapping_header_t*)&seg_mapping_base; 
821    mapping_cluster_t*  cluster = boot_get_cluster_base( header ); 
822    mapping_periph_t*   periph  = boot_get_periph_base( header );
823
824    // checking mapping availability
825    if ( header->signature != IN_MAPPING_SIGNATURE )
826    {
827        boot_puts("\n[BOOT ERROR] Illegal mapping signature: ");
828        boot_putx(header->signature);
829        boot_puts("\n");
830        boot_exit();
831    }
832
833    // checking number of clusters
834    if ( header->clusters != NB_CLUSTERS )
835    {
836        boot_puts("\n[BOOT ERROR] Incoherent NB_CLUSTERS");
837        boot_puts("\n             - In giet_config,  value = ");
838        boot_putd ( NB_CLUSTERS );
839        boot_puts("\n             - In mapping_info, value = ");
840        boot_putd ( header->clusters );
841        boot_puts("\n");
842        boot_exit();
843    }
844
845    // checking number of virtual spaces
846    if ( header->vspaces > GIET_NB_VSPACE_MAX )
847    {
848        boot_puts("\n[BOOT ERROR] : number of vspaces > GIET_NB_VSPACE_MAX\n");
849        boot_puts("\n");
850        boot_exit();
851    }
852
853    // checking hardware
854    unsigned int periph_id;
855    unsigned int cluster_id;
856    unsigned int tty_found = 0;
857    unsigned int nic_found = 0;
858    for ( cluster_id = 0 ; cluster_id < NB_CLUSTERS ; cluster_id++ )
859    {
860        // NB_PROCS_MAX
861        if ( cluster[cluster_id].procs > NB_PROCS_MAX )
862        {
863            boot_puts("\n[BOOT ERROR] too much processors in cluster ");
864            boot_putd( cluster_id );
865            boot_puts(" : procs = ");
866            boot_putd ( cluster[cluster_id].procs );
867            boot_puts("\n");
868            boot_exit();
869        }
870
871        for ( periph_id = cluster[cluster_id].periph_offset ;
872              periph_id < cluster[cluster_id].periph_offset + cluster[cluster_id].periphs ;
873              periph_id++ )
874        {
875            // NB_TTYS
876            if ( periph[periph_id].type == PERIPH_TYPE_TTY ) 
877            {
878                if ( tty_found )
879                {
880                    boot_puts("\n[BOOT ERROR] TTY component should not be replicated\n");
881                    boot_exit();
882                }
883                if ( periph[periph_id].channels != NB_TTYS )
884                {
885                    boot_puts("\n[BOOT ERROR] Wrong NB_TTYS in cluster ");
886                    boot_putd( cluster_id );
887                    boot_puts(" : ttys = ");
888                    boot_putd ( periph[periph_id].channels );
889                    boot_puts("\n");
890                    boot_exit();
891                }
892                tty_found = 1;
893            }
894            // NB_NICS
895            if ( periph[periph_id].type == PERIPH_TYPE_NIC ) 
896            {
897                if ( nic_found )
898                {
899                    boot_puts("\n[BOOT ERROR] NIC component should not be replicated\n");
900                    boot_exit();
901                }
902                if ( periph[periph_id].channels != NB_NICS )
903                {
904                    boot_puts("\n[BOOT ERROR] Wrong NB_NICS in cluster ");
905                    boot_putd( cluster_id );
906                    boot_puts(" : nics = ");
907                    boot_putd ( periph[periph_id].channels );
908                    boot_puts("\n");
909                    boot_exit();
910                }
911                nic_found = 1;
912            }
913            // NB_TIMERS
914            if ( periph[periph_id].type == PERIPH_TYPE_TIM ) 
915            {
916                if ( periph[periph_id].channels != (NB_PROCS_MAX + NB_TIMERS_MAX) )
917                {
918                    boot_puts("\n[BOOT ERROR] Too much user timers in cluster ");
919                    boot_putd( cluster_id );
920                    boot_puts(" : timers = ");
921                    boot_putd ( periph[periph_id].channels );
922                    boot_puts("\n");
923                    boot_exit();
924                }
925            }
926            // NB_DMAS
927            if ( periph[periph_id].type == PERIPH_TYPE_DMA ) 
928            {
929                if ( periph[periph_id].channels != NB_DMAS_MAX )
930                {
931                    boot_puts("\n[BOOT ERROR] Too much DMA channels in cluster ");
932                    boot_putd( cluster_id );
933                    boot_puts(" : channels = ");
934                    boot_putd ( periph[periph_id].channels );
935                    boot_puts("\n");
936                    boot_exit();
937                }
938            }
939        } // end for periphs
940    } // end for clusters
941} // end boot_check_mapping()
942
943/////////////////////////////////////////////////////////////////////
944// This function initialises the physical pages table allocators
945// for all psegs (i.e. next_base field of the pseg).
946// In each cluster containing processors, it reserve space for the
947// schedulers in the first RAM pseg found (4k bytes per processor).
948/////////////////////////////////////////////////////////////////////
949void boot_psegs_init()
950{
951    mapping_header_t*   header  = (mapping_header_t*)&seg_mapping_base; 
952
953    mapping_cluster_t*  cluster = boot_get_cluster_base( header ); 
954    mapping_pseg_t*     pseg    = boot_get_pseg_base( header ); 
955
956    unsigned int cluster_id;
957    unsigned int pseg_id;
958    unsigned int found;
959
960#if BOOT_DEBUG_PT
961boot_puts("\n[BOOT DEBUG] ****** psegs allocators nitialisation ******\n");
962#endif
963
964    for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
965    {
966        if ( cluster[cluster_id].procs > NB_PROCS_MAX )
967        {
968            boot_puts("\n[BOOT ERROR] The number of processors in cluster ");
969            boot_putd( cluster_id );
970            boot_puts(" is larger than NB_PROCS_MAX \n");
971            boot_exit();
972        }
973
974        found    = 0;
975
976        for ( pseg_id = cluster[cluster_id].pseg_offset ;
977              pseg_id < cluster[cluster_id].pseg_offset + cluster[cluster_id].psegs ;
978              pseg_id++ )
979        {
980            unsigned int free = pseg[pseg_id].base;
981
982            if ( (pseg[pseg_id].type == PSEG_TYPE_RAM) && (found == 0) )
983            {
984                free = free + (cluster[cluster_id].procs << 12);
985                found = 1;
986            }
987            pseg[pseg_id].next_base = free;
988
989#if BOOT_DEBUG_PT
990boot_puts("cluster ");
991boot_putd(cluster_id);
992boot_puts(" / pseg ");
993boot_puts(pseg[pseg_id].name);
994boot_puts(" : next_base = ");
995boot_putx(pseg[pseg_id].next_base);
996boot_puts("\n");
997#endif
998        }
999    }
1000} // end boot_pseg_init()
1001
1002/////////////////////////////////////////////////////////////////////
1003// This function builds the page tables for all virtual spaces
1004// defined in the mapping_info data structure.
1005// For each virtual space, it maps both the global vsegs
1006// (replicated in all vspaces), and the private vsegs.
1007/////////////////////////////////////////////////////////////////////
1008void boot_pt_init()
1009{
1010    mapping_header_t*   header = (mapping_header_t*)&seg_mapping_base; 
1011
1012    mapping_vspace_t*   vspace = boot_get_vspace_base( header );     
1013    mapping_vseg_t*     vseg   = boot_get_vseg_base( header );
1014
1015    unsigned int        vspace_id; 
1016    unsigned int        vseg_id;
1017
1018#if BOOT_DEBUG_PT
1019boot_puts("\n[BOOT DEBUG] ****** mapping global vsegs ******\n");
1020#endif
1021           
1022    // step 1 : first loop on virtual spaces to map global vsegs
1023    for ( vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
1024    {
1025        boot_vseg_map( &vseg[vseg_id], ((unsigned int)(-1)) );
1026    }
1027
1028    // step 2 : loop on virtual vspaces to map private vsegs
1029    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
1030    {
1031
1032#if BOOT_DEBUG_PT
1033boot_puts("\n[BOOT DEBUG] ****** mapping private vsegs in vspace ");
1034boot_puts(vspace[vspace_id].name);
1035boot_puts(" ******\n");
1036#endif
1037           
1038        for ( vseg_id = vspace[vspace_id].vseg_offset ; 
1039              vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
1040              vseg_id++ )
1041        {
1042            boot_vseg_map( &vseg[vseg_id], vspace_id ); 
1043        }
1044    } 
1045
1046    // step 3 : loop on the vspaces to build the page tables
1047    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
1048    {
1049
1050#if BOOT_DEBUG_PT
1051boot_puts("\n[BOOT DEBUG] ****** building page table for vspace ");
1052boot_puts(vspace[vspace_id].name);
1053boot_puts(" ******\n");
1054#endif
1055           
1056        boot_vspace_pt_build( vspace_id );
1057
1058#if BOOT_DEBUG_PT
1059boot_puts("\n>>> page table physical address = ");
1060boot_putx((unsigned int)boot_ptabs_paddr[vspace_id]);
1061boot_puts(", page table number of PT2 = ");
1062boot_putd((unsigned int)boot_max_pt2[vspace_id]);
1063boot_puts("\n");
1064#endif
1065    } 
1066} // end boot_pt_init()
1067
1068///////////////////////////////////////////////////////////////////////////////
1069// This function initializes all private vobjs defined in the vspaces,
1070// such as mwmr channels, barriers and locks, because these vobjs
1071// are not known, and not initialised by the compiler.
1072///////////////////////////////////////////////////////////////////////////////
1073void boot_vobjs_init()
1074{
1075    mapping_header_t*   header  = (mapping_header_t*)&seg_mapping_base; 
1076    mapping_vspace_t*   vspace  = boot_get_vspace_base( header );     
1077    mapping_vobj_t*     vobj    = boot_get_vobj_base( header );
1078
1079    unsigned int        vspace_id; 
1080    unsigned int        vobj_id;
1081
1082    // loop on the vspaces
1083    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
1084    {
1085
1086#if BOOT_DEBUG_VOBJS
1087boot_puts("\n[BOOT DEBUG] ****** vobjs initialisation in vspace "); 
1088boot_puts(vspace[vspace_id].name);
1089boot_puts(" ******\n");
1090#endif
1091
1092        unsigned int ptab_found = 0;
1093
1094        // loop on the vobjs
1095            for(vobj_id= vspace[vspace_id].vobj_offset; 
1096                        vobj_id < (vspace[vspace_id].vobj_offset+ vspace[vspace_id].vobjs);
1097                        vobj_id++)
1098            {
1099            switch( vobj[vobj_id].type )
1100            {
1101                case VOBJ_TYPE_MWMR:    // storage capacity is (vobj.length/4 - 5) words
1102                        {
1103                    mwmr_channel_t* mwmr = (mwmr_channel_t*)(vobj[vobj_id].paddr);
1104                    mwmr->ptw   = 0;
1105                    mwmr->ptr   = 0;
1106                    mwmr->sts   = 0;
1107                    mwmr->width = vobj[vobj_id].init;
1108                    mwmr->depth = (vobj[vobj_id].length>>2) - 6;
1109                    mwmr->lock  = 0;
1110#if BOOT_DEBUG_VOBJS
1111boot_puts("MWMR    : ");
1112boot_puts( vobj[vobj_id].name);
1113boot_puts(" / depth = ");
1114boot_putd( mwmr->depth );
1115boot_puts(" / width = ");
1116boot_putd( mwmr->width );
1117boot_puts("\n");
1118#endif
1119                    break;
1120                }
1121                case VOBJ_TYPE_ELF:             // initialisation done by the loader
1122                {
1123#if BOOT_DEBUG_VOBJS
1124boot_puts("ELF     : ");
1125boot_puts( vobj[vobj_id].name);
1126boot_puts(" / length = ");
1127boot_putx( vobj[vobj_id].length ); 
1128boot_puts("\n");
1129#endif
1130                    break;
1131                }
1132                case VOBJ_TYPE_BLOB:            // initialisation done by the loader
1133                {
1134#if BOOT_DEBUG_VOBJS
1135boot_puts("BLOB     : ");
1136boot_puts( vobj[vobj_id].name);
1137boot_puts(" / length = ");
1138boot_putx( vobj[vobj_id].length ); 
1139boot_puts("\n");
1140#endif
1141                    break;
1142                }
1143                case VOBJ_TYPE_BARRIER: // init is the number of participants
1144                {
1145                    giet_barrier_t* barrier = (giet_barrier_t*)(vobj[vobj_id].paddr);
1146                    barrier->count = 0;
1147                    barrier->init  = vobj[vobj_id].init;
1148#if BOOT_DEBUG_VOBJS
1149boot_puts("BARRIER : ");
1150boot_puts( vobj[vobj_id].name);
1151boot_puts(" / init_value = ");
1152boot_putd( barrier->init );
1153boot_puts("\n");
1154#endif
1155                    break;
1156                }
1157                case VOBJ_TYPE_LOCK:    // init is "not taken"
1158                {
1159                    unsigned int* lock = (unsigned int*)(vobj[vobj_id].paddr);
1160                    *lock = 0;
1161#if BOOT_DEBUG_VOBJS
1162boot_puts("LOCK    : ");
1163boot_puts( vobj[vobj_id].name);
1164boot_puts("\n");
1165#endif
1166                    break;
1167                }
1168                case VOBJ_TYPE_BUFFER:  // nothing to initialise
1169                {
1170#if BOOT_DEBUG_VOBJS
1171boot_puts("BUFFER  : ");
1172boot_puts( vobj[vobj_id].name);
1173boot_puts(" / length = ");
1174boot_putx( vobj[vobj_id].length ); 
1175boot_puts("\n");
1176#endif
1177                    break;
1178                }
1179                case VOBJ_TYPE_PTAB:    // nothing to initialise
1180                {
1181                    ptab_found = 1;
1182#if BOOT_DEBUG_VOBJS
1183boot_puts("PTAB    : ");
1184boot_puts( vobj[vobj_id].name);
1185boot_puts(" / length = ");
1186boot_putx( vobj[vobj_id].length ); 
1187boot_puts("\n");
1188#endif
1189                    break;
1190                }
1191                default:
1192                {
1193                    boot_puts("\n[INIT ERROR] illegal vobj of name ");
1194                    boot_puts(vobj->name);
1195                    boot_puts(" / in vspace = ");
1196                    boot_puts(vobj->name);
1197                    boot_puts("\n ");
1198                    boot_exit();
1199                }
1200            } // end switch type
1201        } // end loop on vobjs
1202        if( ptab_found == 0 )
1203        {
1204            boot_puts("\n[INIT ERROR] Missing PTAB for vspace ");
1205            boot_putd( vspace_id );
1206            boot_exit();
1207        }
1208    } // end loop on vspaces
1209} // end boot_vobjs_init()
1210
1211void
1212mwmr_hw_init( void *coproc, enum mwmrPortDirection way,
1213              unsigned int no, const mwmr_channel_t *pmwmr)
1214{
1215    volatile unsigned int *cbase = (unsigned int*) coproc;
1216   
1217    cbase[MWMR_CONFIG_FIFO_WAY] = way ;
1218    cbase[MWMR_CONFIG_FIFO_NO] = no ;
1219    cbase[MWMR_CONFIG_STATUS_ADDR] = (unsigned int)pmwmr ;
1220    cbase[MWMR_CONFIG_WIDTH] = pmwmr->width ;
1221    cbase[MWMR_CONFIG_DEPTH] = pmwmr->depth;
1222    cbase[MWMR_CONFIG_BUFFER_ADDR] = (unsigned int)&pmwmr->data;
1223    cbase[MWMR_CONFIG_RUNNING] = 1 ;
1224}
1225
1226
1227////////////////////////////////////////////////////////////////////////////////
1228// This function intializes the periherals and coprocessors, as specified
1229// in the mapping_info file.
1230////////////////////////////////////////////////////////////////////////////////
1231void boot_peripherals_init()
1232{
1233    mapping_header_t*   header  = (mapping_header_t*)&seg_mapping_base; 
1234    mapping_cluster_t*  cluster = boot_get_cluster_base( header );     
1235    mapping_periph_t*   periph  = boot_get_periph_base( header );
1236    mapping_pseg_t*     pseg    = boot_get_pseg_base( header );
1237    mapping_vobj_t*     vobj    = boot_get_vobj_base( header );
1238    mapping_vspace_t*   vspace  = boot_get_vspace_base( header );     
1239    mapping_coproc_t*   coproc  = boot_get_coproc_base( header );
1240    mapping_cp_port_t*  cp_port = boot_get_cp_port_base( header );
1241
1242    unsigned int        cluster_id;
1243    unsigned int        periph_id; 
1244    unsigned int        coproc_id; 
1245    unsigned int        cp_port_id; 
1246    unsigned int        channel_id;
1247
1248    for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
1249    {
1250
1251#if BOOT_DEBUG_PERI
1252boot_puts("\n[BOOT DEBUG] ****** peripheral initialisation in cluster "); 
1253boot_putd( cluster_id );
1254boot_puts(" ******\n");
1255#endif
1256
1257        for ( periph_id = cluster[cluster_id].periph_offset ;
1258              periph_id < cluster[cluster_id].periph_offset + cluster[cluster_id].periphs ;
1259              periph_id++ )
1260        {
1261            unsigned int    type      = periph[periph_id].type;
1262            unsigned int    channels  = periph[periph_id].channels;
1263            unsigned int    pseg_id   = periph[periph_id].psegid;
1264
1265            unsigned int*   pseg_base = (unsigned int*)pseg[pseg_id].base;
1266
1267            //////// vci_block_device component
1268            if      ( type == PERIPH_TYPE_IOC )
1269            {
1270
1271                // activate interrupts
1272                pseg_base[BLOCK_DEVICE_IRQ_ENABLE] = 1; 
1273
1274#if BOOT_DEBUG_PERI
1275boot_puts("- IOC initialised : ");
1276boot_putd( channels );
1277boot_puts(" channels\n");
1278#endif
1279            }
1280
1281            //////// vci_multi_dma component
1282            else if ( type == PERIPH_TYPE_DMA )
1283            {
1284                for ( channel_id = 0 ; channel_id < channels ; channel_id++ )
1285                { 
1286                    // activate interrupts
1287                    pseg_base[DMA_IRQ_DISABLE + channel_id*DMA_SPAN] = 0;
1288                }
1289
1290#if BOOT_DEBUG_PERI
1291boot_puts("- DMA initialised : ");
1292boot_putd( channels );
1293boot_puts(" channels\n");
1294#endif
1295            }
1296
1297            //////// vci_multi_nic component
1298            else if ( type == PERIPH_TYPE_NIC  )
1299            {
1300                for ( channel_id = 0 ; channel_id < channels ; channel_id++ )
1301                { 
1302                // TODO
1303                }
1304
1305#if BOOT_DEBUG_PERI
1306boot_puts("- NIC initialised : ");
1307boot_putd( channels );
1308boot_puts(" channels\n");
1309#endif
1310            }
1311
1312            //////// vci_io_bridge component
1313            else if ( (type == PERIPH_TYPE_IOB) && GIET_IOMMU_ACTIVE )
1314            {
1315                // get the iommu page table physical address
1316                // TODO
1317
1318                // define IPI address mapping the IOC interrupt
1319                // TODO
1320
1321                // set IOMMU page table address
1322                // pseg_base[IOB_IOMMU_PTPR] = ptab_pbase;   
1323
1324                // activate IOMMU
1325                // pseg_base[IOB_IOMMU_ACTIVE] = 1;       
1326
1327#if BOOT_DEBUG_PERI
1328boot_puts("- IOB initialised : ");
1329boot_putd( channels );
1330boot_puts(" channels\n");
1331#endif
1332            }
1333
1334        } // end for periphs
1335
1336        for ( coproc_id = cluster[cluster_id].coproc_offset ;
1337              coproc_id < cluster[cluster_id].coproc_offset + cluster[cluster_id].coprocs ;
1338              coproc_id++ )
1339        {
1340            unsigned no_fifo_to  = 0;       //FIXME: should it be the map.xml who define the order?
1341            unsigned no_fifo_from = 0;
1342            unsigned int cpseg = pseg[coproc[coproc_id].psegid].base;
1343
1344#if BOOT_DEBUG_PERI
1345boot_puts("[BOOT] mwmr coproc initialisation of ");
1346boot_puts((unsigned int) coproc[coproc_id].name);
1347boot_puts(", nb ports");
1348boot_putd((unsigned int)coproc[coproc_id].ports);
1349boot_puts("\n");
1350#endif
1351
1352            for ( cp_port_id = coproc[coproc_id].port_offset ;
1353                  cp_port_id < coproc[coproc_id].port_offset + coproc[coproc_id].ports ;
1354                  cp_port_id++ )
1355            {
1356                //FIXME: the vspace_id should be the same for all ports: put it in the coproc?
1357                unsigned int vspace_id  = cp_port[cp_port_id].vspaceid; 
1358                unsigned int vobj_id    = cp_port[cp_port_id].vobjlocid + vspace[vspace_id].vobj_offset;
1359
1360                mwmr_channel_t *pmwmr = (mwmr_channel_t*)(vobj[vobj_id].paddr);
1361
1362                if( cp_port[cp_port_id].direction == PORT_TO_COPROC)
1363                {
1364
1365#if BOOT_DEBUG_PERI
1366boot_puts("     port direction: PORT_TO_COPROC");
1367#endif
1368                    mwmr_hw_init((void*)cpseg, PORT_TO_COPROC, no_fifo_to, pmwmr );
1369                    no_fifo_to++;
1370                }
1371                else
1372                {
1373#if BOOT_DEBUG_PERI
1374boot_puts("     port direction: PORT_FROM_COPROC");
1375#endif
1376                    mwmr_hw_init((void*)cpseg, PORT_FROM_COPROC, no_fifo_from, pmwmr );
1377                    no_fifo_from++;
1378                }
1379#if BOOT_DEBUG_PERI
1380boot_puts(", with mwmr: ");
1381boot_puts(vobj[vobj_id].name);
1382boot_puts(" of vspace: ");
1383boot_puts(vspace[vspace_id].name);
1384#endif
1385            }
1386        } // end for coprocs
1387
1388    } // end for clusters
1389} // end boot_peripherals_init()
1390
1391
1392///////////////////////////////////////////////////////////////////////////////
1393// This function initialises all processors schedulers.
1394// This is done by processor 0, and the MMU must be activated.
1395// It initialises the boot_schedulers_paddr[gpid] pointers array.
1396// Finally, it scan all tasks in all vspaces to initialise the tasks contexts,
1397// as specified in the mapping_info data structure.
1398// For each task, a TTY channel, a TIMER channel, a FBDMA channel, and a NIC
1399// channel can be allocated if required.
1400///////////////////////////////////////////////////////////////////////////////
1401void boot_schedulers_init()
1402{
1403    mapping_header_t*   header  = (mapping_header_t*)&seg_mapping_base; 
1404    mapping_cluster_t*  cluster = boot_get_cluster_base( header );
1405    mapping_pseg_t*     pseg    = boot_get_pseg_base( header );
1406    mapping_vspace_t*   vspace  = boot_get_vspace_base( header );     
1407    mapping_task_t*     task    = boot_get_task_base( header );
1408    mapping_vobj_t*     vobj    = boot_get_vobj_base( header );
1409    mapping_proc_t*     proc    = boot_get_proc_base( header );
1410    mapping_irq_t*      irq     = boot_get_irq_base( header );
1411
1412    unsigned int        alloc_tty_channel;                 // TTY channel allocator
1413    unsigned int        alloc_nic_channel;                 // NIC channel allocator
1414    unsigned int        alloc_fbdma_channel[NB_CLUSTERS];  // FBDMA channel allocators
1415    unsigned int        alloc_timer_channel[NB_CLUSTERS];  // user TIMER allocators
1416
1417    unsigned int        cluster_id;                        // cluster global index
1418    unsigned int        proc_id;                           // processor global index
1419    unsigned int        irq_id;                            // irq global index
1420    unsigned int        pseg_id;                           // pseg global index
1421    unsigned int        vspace_id;                         // vspace global index
1422    unsigned int        task_id;                           // task global index;
1423
1424    // Step 0 : TTY, NIC, TIMERS and DMA channels allocators initialisation
1425    //          global_id = cluster_id*NB_*_MAX + loc_id
1426    //          - TTY[0] is reserved for the kernel
1427    //          - In all clusters the first NB_PROCS_MAX timers
1428    //            are reserved for the kernel (context switch)
1429
1430    alloc_tty_channel = 1; 
1431    alloc_nic_channel = 0;
1432
1433    for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
1434    {
1435        alloc_fbdma_channel[cluster_id] = 0;
1436        alloc_timer_channel[cluster_id] = NB_PROCS_MAX;
1437    }
1438               
1439    // Step 1 : loop on the clusters and on the processors
1440    //          - initialise the boot_schedulers_paddr[] pointers array
1441    //          - initialise the interrupt vectors for each processor.
1442
1443    for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
1444    {
1445
1446#if BOOT_DEBUG_SCHED
1447boot_puts("\n[BOOT DEBUG] Initialise schedulers / IT vector in cluster ");
1448boot_putd( cluster_id );
1449boot_puts("\n");
1450#endif
1451        unsigned int found = 0;
1452        unsigned int pseg_pbase;           // pseg base address
1453        unsigned int lpid;                 // processor local index
1454
1455        // get the physical base address of the first PSEG_TYPE_RAM pseg in cluster
1456        for ( pseg_id = cluster[cluster_id].pseg_offset ; 
1457              pseg_id < cluster[cluster_id].pseg_offset + cluster[cluster_id].psegs ; 
1458              pseg_id++ )
1459        {
1460            if ( pseg[pseg_id].type == PSEG_TYPE_RAM ) 
1461            {
1462                pseg_pbase = pseg[pseg_id].base;
1463                found = 1;
1464                break;
1465            }
1466        }
1467
1468        if ( (cluster[cluster_id].procs > 0) && (found == 0) )
1469        {
1470            boot_puts("\n[BOOT ERROR] Missing RAM pseg in cluster ");
1471            boot_putd( cluster_id );
1472            boot_puts("\n");
1473            boot_exit();
1474        }
1475
1476        // 4 Kbytes per scheduler
1477        for ( lpid = 0 ; lpid < cluster[cluster_id].procs ; lpid++ )
1478        {
1479            boot_schedulers_paddr[cluster_id*NB_PROCS_MAX + lpid] =
1480                (static_scheduler_t*)( pseg_pbase + (lpid<<12) );
1481        }
1482
1483        for ( proc_id = cluster[cluster_id].proc_offset ;
1484              proc_id < cluster[cluster_id].proc_offset + cluster[cluster_id].procs ;
1485              proc_id++ )
1486        {
1487
1488#if BOOT_DEBUG_SCHED
1489boot_puts("\nProc ");
1490boot_putd( proc_id );
1491boot_puts(" : scheduler pbase = ");
1492boot_putx( pseg_pbase + (proc_id<<12) );
1493boot_puts("\n");
1494#endif
1495            // initialise the "tasks" variable in scheduler
1496            boot_scheduler_set_tasks( proc_id , 0 );
1497           
1498            // initialise the interrupt_vector with ISR_DEFAULT
1499            unsigned int slot;
1500            for ( slot = 0 ; slot < 32 ; slot++) 
1501            {
1502                boot_scheduler_set_itvector( proc_id, slot, 0);
1503            }
1504
1505            // scan the IRQs actually allocated to current processor
1506            for ( irq_id = proc[proc_id].irq_offset ;
1507                  irq_id < proc[proc_id].irq_offset + proc[proc_id].irqs ;
1508                  irq_id++ )
1509            {
1510                unsigned int type    = irq[irq_id].type;
1511                unsigned int icu_id  = irq[irq_id].icuid;
1512                unsigned int isr_id  = irq[irq_id].isr;
1513                unsigned int channel = irq[irq_id].channel;
1514                unsigned int value   = isr_id | (type<<8) | (channel<<16); 
1515                boot_scheduler_set_itvector( proc_id, icu_id, value );
1516
1517#if BOOT_DEBUG_SCHED
1518boot_puts("- IRQ : icu = ");
1519boot_putd( icu_id );
1520boot_puts(" / type = ");
1521boot_putd( type );
1522boot_puts(" / isr = ");
1523boot_putd( isr_id );
1524boot_puts(" / channel = ");
1525boot_putd( channel );
1526boot_puts("\n");
1527#endif
1528            }
1529        } // end for procs
1530    } // end for clusters
1531
1532    // Step 2 : loop on the vspaces and the tasks
1533    //          to initialise the schedulers and the task contexts.
1534
1535    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
1536    {
1537
1538#if BOOT_DEBUG_SCHED
1539boot_puts("\n[BOOT DEBUG] Initialise schedulers / task contexts for vspace ");
1540boot_puts(vspace[vspace_id].name);
1541boot_puts("\n");
1542#endif
1543        // We must set the PTPR depending on the vspace, because the start_vector
1544        // and the stack address are defined in virtual space.
1545        boot_set_mmu_ptpr( (unsigned int)boot_ptabs_paddr[vspace_id] >> 13 );
1546
1547        // loop on the tasks in vspace (task_id is the global index)
1548        for ( task_id = vspace[vspace_id].task_offset ; 
1549              task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks) ; 
1550              task_id++ )
1551        {
1552            // ctx_ra :  the return address is &boot_eret()
1553            unsigned int ctx_ra = (unsigned int)&boot_eret;
1554
1555            // ctx_sr : value required before an eret instruction
1556            unsigned int ctx_sr = 0x0000FF13; 
1557
1558            // ctx_ptpr : page table physical base address (shifted by 13 bit)
1559            unsigned int ctx_ptpr = (unsigned int)boot_ptabs_paddr[vspace_id] >> 13;
1560
1561            // ctx_ptab : page_table virtual base address
1562            unsigned int ctx_ptab = (unsigned int)boot_ptabs_vaddr[vspace_id];
1563
1564            // ctx_tty : terminal global index provided by a global allocator
1565            unsigned int ctx_tty = 0xFFFFFFFF;
1566            if ( task[task_id].use_tty ) 
1567            {
1568                if ( alloc_tty_channel >= NB_TTYS )
1569                {
1570                    boot_puts("\n[BOOT ERROR] TTY index too large for task ");
1571                    boot_puts( task[task_id].name );
1572                    boot_puts(" in vspace ");
1573                    boot_puts( vspace[vspace_id].name );
1574                    boot_puts("\n");
1575                    boot_exit();
1576                }
1577                ctx_tty = alloc_tty_channel;
1578                alloc_tty_channel++;
1579            }
1580
1581            // ctx_nic : NIC channel global index provided by a global allocator
1582            unsigned int ctx_nic = 0xFFFFFFFF;
1583            if ( task[task_id].use_nic ) 
1584            {
1585                if ( alloc_nic_channel >= NB_NICS )
1586                {
1587                    boot_puts("\n[BOOT ERROR] NIC channel index too large for task ");
1588                    boot_puts( task[task_id].name );
1589                    boot_puts(" in vspace ");
1590                    boot_puts( vspace[vspace_id].name );
1591                    boot_puts("\n");
1592                    boot_exit();
1593                }
1594                ctx_nic = alloc_nic_channel;
1595                alloc_nic_channel++;
1596            }
1597
1598            // ctx_timer : user TIMER global index provided by a cluster allocator
1599            unsigned int ctx_timer = 0xFFFFFFFF;
1600            if ( task[task_id].use_timer ) 
1601            {
1602                unsigned int cluster_id = task[task_id].clusterid;
1603                if ( alloc_timer_channel[cluster_id] >= NB_TIMERS_MAX )
1604                {
1605                    boot_puts("\n[BOOT ERROR] local TIMER index too large for task ");
1606                    boot_puts( task[task_id].name );
1607                    boot_puts(" in vspace ");
1608                    boot_puts( vspace[vspace_id].name );
1609                    boot_puts("\n");
1610                    boot_exit();
1611                }
1612                ctx_timer = cluster_id*NB_TIMERS_MAX + alloc_timer_channel[cluster_id];
1613                alloc_timer_channel[cluster_id]++;
1614            }
1615
1616            // ctx_fbdma : DMA global index provided by a cluster allocator 
1617            unsigned int ctx_fbdma = 0xFFFFFFFF;
1618            if ( task[task_id].use_fbdma ) 
1619            {
1620                unsigned int cluster_id = task[task_id].clusterid;
1621                if ( alloc_fbdma_channel[cluster_id] >= NB_DMAS_MAX )
1622                {
1623                    boot_puts("\n[BOOT ERROR] local FBDMA index too large for task ");
1624                    boot_puts( task[task_id].name );
1625                    boot_puts(" in vspace ");
1626                    boot_puts( vspace[vspace_id].name );
1627                    boot_puts("\n");
1628                    boot_exit();
1629                }
1630                ctx_fbdma = cluster_id*NB_DMAS_MAX + alloc_fbdma_channel[cluster_id];
1631                alloc_fbdma_channel[cluster_id]++;
1632            }
1633
1634            // ctx_epc : Get the virtual address of the start function
1635            mapping_vobj_t* pvobj = &vobj[vspace[vspace_id].vobj_offset + 
1636                                          vspace[vspace_id].start_offset]; 
1637            unsigned int* start_vector_vbase = (unsigned int*)pvobj->vaddr;
1638            unsigned int ctx_epc = start_vector_vbase[task[task_id].startid];
1639
1640            // ctx_sp :  Get the vobj containing the stack
1641            unsigned int vobj_id = task[task_id].vobjlocid + vspace[vspace_id].vobj_offset;
1642            unsigned int ctx_sp = vobj[vobj_id].vaddr + vobj[vobj_id].length;
1643
1644            // compute gpid = global processor index
1645            unsigned int gpid = task[task_id].clusterid*NB_PROCS_MAX + 
1646                                task[task_id].proclocid;
1647
1648            // In the code below, we access the scheduler with specific access
1649            // functions, because we only have the physical address of the scheduler,
1650            // and these functions must temporary desactivate the DTLB...
1651
1652            // get local task index in scheduler[gpid]
1653            unsigned int ltid = boot_scheduler_get_tasks( gpid );
1654
1655            if ( ltid >= IDLE_TASK_INDEX )
1656            {
1657                boot_puts("\n[BOOT ERROR] : ");
1658                boot_putd( ltid );
1659                boot_puts(" tasks allocated to processor ");
1660                boot_putd( gpid );
1661                boot_puts(" / max is 15\n");
1662                boot_exit();
1663            }
1664
1665            // update the "tasks" field in scheduler[gpid]
1666            boot_scheduler_set_tasks( gpid, ltid + 1);
1667
1668            // update the "current" field in scheduler[gpid]
1669            boot_scheduler_set_current( gpid, 0 );
1670
1671            // initializes the task context in scheduler[gpid]
1672            boot_scheduler_set_context( gpid, ltid, CTX_SR_ID    , ctx_sr     );
1673            boot_scheduler_set_context( gpid, ltid, CTX_SP_ID    , ctx_sp     );
1674            boot_scheduler_set_context( gpid, ltid, CTX_RA_ID    , ctx_ra     );
1675            boot_scheduler_set_context( gpid, ltid, CTX_EPC_ID   , ctx_epc    );
1676            boot_scheduler_set_context( gpid, ltid, CTX_PTPR_ID  , ctx_ptpr   );
1677            boot_scheduler_set_context( gpid, ltid, CTX_TTY_ID   , ctx_tty    );
1678            boot_scheduler_set_context( gpid, ltid, CTX_FBDMA_ID , ctx_fbdma  );
1679            boot_scheduler_set_context( gpid, ltid, CTX_NIC_ID   , ctx_nic    );
1680            boot_scheduler_set_context( gpid, ltid, CTX_TIMER_ID , ctx_timer  );
1681            boot_scheduler_set_context( gpid, ltid, CTX_PTAB_ID  , ctx_ptab   );
1682            boot_scheduler_set_context( gpid, ltid, CTX_LTID_ID  , ltid       );
1683            boot_scheduler_set_context( gpid, ltid, CTX_VSID_ID  , vspace_id  );
1684            boot_scheduler_set_context( gpid, ltid, CTX_RUN_ID   , 1          );
1685                                       
1686#if BOOT_DEBUG_SCHED
1687boot_puts("\nTask ");
1688boot_puts( task[task_id].name );
1689boot_puts(" allocated to processor ");
1690boot_putd( gpid );
1691boot_puts("  - ctx[LTID]   = ");
1692boot_putd( ltid );
1693boot_puts("\n");
1694
1695boot_puts("  - ctx[SR]     = ");
1696boot_putx( ctx_sr );
1697boot_puts("\n");
1698
1699boot_puts("  - ctx[SR]     = ");
1700boot_putx( ctx_sp );
1701boot_puts("\n");
1702
1703boot_puts("  - ctx[RA]     = ");
1704boot_putx( ctx_ra );
1705boot_puts("\n");
1706
1707boot_puts("  - ctx[EPC]    = ");
1708boot_putx( ctx_epc );
1709boot_puts("\n");
1710
1711boot_puts("  - ctx[PTPR]   = ");
1712boot_putx( ctx_ptpr );
1713boot_puts("\n");
1714
1715boot_puts("  - ctx[TTY]    = ");
1716boot_putd( ctx_tty );
1717boot_puts("\n");
1718
1719boot_puts("  - ctx[NIC]    = ");
1720boot_putd( ctx_nic );
1721boot_puts("\n");
1722
1723boot_puts("  - ctx[TIMER]  = ");
1724boot_putd( ctx_timer );
1725boot_puts("\n");
1726
1727boot_puts("  - ctx[FBDMA]  = ");
1728boot_putd( ctx_fbdma );
1729boot_puts("\n");
1730
1731boot_puts("  - ctx[PTAB]   = ");
1732boot_putx( ctx_ptab );
1733boot_puts("\n");
1734
1735boot_puts("  - ctx[VSID]   = ");
1736boot_putd( vspace_id );
1737boot_puts("\n");
1738
1739#endif
1740
1741        } // end loop on tasks
1742    } // end loop on vspaces
1743} // end boot_schedulers_init()
1744
1745//////////////////////////////////////////////////////////////////////////////////
1746// This function is executed by P[0] to wakeup all processors.
1747//////////////////////////////////////////////////////////////////////////////////
1748void boot_start_all_procs()
1749{
1750    mapping_header_t*   header = (mapping_header_t*)&seg_mapping_base; 
1751    header->signature = OUT_MAPPING_SIGNATURE;
1752}
1753
1754/////////////////////////////////////////////////////////////////////
1755// This function is the entry point of the initialisation procedure
1756/////////////////////////////////////////////////////////////////////
1757void boot_init()
1758{
1759    // mapping_info checking
1760    boot_check_mapping();
1761
1762    boot_puts("\n[BOOT] Mapping check completed at cycle ");
1763    boot_putd( boot_proctime() );
1764    boot_puts("\n");
1765
1766    // pseg allocators initialisation
1767    boot_psegs_init();
1768
1769    boot_puts("\n[BOOT] Pseg allocators initialisation completed at cycle ");
1770    boot_putd( boot_proctime() );
1771    boot_puts("\n");
1772
1773    // page table building
1774    boot_pt_init();
1775
1776    boot_puts("\n[BOOT] Page Tables initialisation completed at cycle ");
1777    boot_putd( boot_proctime() );
1778    boot_puts("\n");
1779
1780    // vobjs initialisation
1781    boot_vobjs_init();
1782
1783    boot_puts("\n[BOOT] Vobjs initialisation completed at cycle : ");
1784    boot_putd( boot_proctime() );
1785    boot_puts("\n");
1786
1787    // peripherals initialisation
1788    boot_peripherals_init();
1789
1790    boot_puts("\n[BOOT] Peripherals initialisation completed at cycle ");
1791    boot_putd( boot_proctime() );
1792    boot_puts("\n");
1793
1794    // mmu activation
1795    boot_set_mmu_ptpr( (unsigned int)boot_ptabs_paddr[0] >> 13 );
1796    boot_set_mmu_mode( 0xF );
1797
1798    boot_puts("\n[BOOT] MMU activation completed at cycle ");
1799    boot_putd( boot_proctime() );
1800    boot_puts("\n");
1801
1802    // schedulers initialisation
1803    boot_schedulers_init();
1804
1805    boot_puts("\n[BOOT] Schedulers initialisation completed at cycle ");
1806    boot_putd( boot_proctime() );
1807    boot_puts("\n");
1808
1809    // start all processors
1810    boot_start_all_procs();
1811
1812} // end boot_init()
1813
1814// Local Variables:
1815// tab-width: 4
1816// c-basic-offset: 4
1817// c-file-offsets:((innamespace . 0)(inline-open . 0))
1818// indent-tabs-mode: nil
1819// End:
1820// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
1821
Note: See TracBrowser for help on using the repository browser.